From 3e2301613bd064d75343e15a43c23087148e6097 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 30 Jun 2015 14:29:31 -0700 Subject: [PATCH 01/85] Updated README in preparation for formal 1.0 release --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aae1bdd..9317919 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,20 @@ # d3-book -======= These are sample code files to accompany the book “Interactive Data Visualization for the Web” by Scott Murray, published in March 2013 by O’Reilly. - [O’Reilly book page](http://shop.oreilly.com/product/0636920026938.do) -- [Free chapter previews](http://ofps.oreilly.com/titles/9781449339739/) +- [Online version with inline examples](http://chimera.labs.oreilly.com/books/1230000000345) +- [Author’s website](http://alignedleft.com/) + + + +### Version + +**Important:** Make sure you are using the correct version of these example files! Otherwise, the examples you see here may not exactly match the ones you see in the book. + +This is version **1.0**. This release matches examples seen in the first edition of the book, published March 2013. + + ### License From 68be2815294994e02a8afa698ea71abd534face7 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 5 Aug 2015 16:16:45 -0700 Subject: [PATCH 02/85] Created LICENSE file --- LICENSE.md | 40 ++++++++++++++++++++++++++++++++++++++++ README.md | 8 -------- 2 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..257409a --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,40 @@ +## D3-BOOK CODE SAMPLES LICENSE + +This work is licensed under a [Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License](http://creativecommons.org/licenses/by-nc-nd/3.0/). + + + +## DATA LICENSES + +TBD + + + +## D3.JS LICENSE + +Copyright (c) 2010-2015, Michael Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* The name Michael Bostock may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md index 9317919..ebbfcc5 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,3 @@ These are sample code files to accompany the book “Interactive Data Visualizat **Important:** Make sure you are using the correct version of these example files! Otherwise, the examples you see here may not exactly match the ones you see in the book. This is version **1.0**. This release matches examples seen in the first edition of the book, published March 2013. - - - -### License - -This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License. - -http://creativecommons.org/licenses/by-nc-nd/3.0/ From 1c23615aa9ba0f9edfc1b98ed51867464f457fb1 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 5 Aug 2015 16:19:21 -0700 Subject: [PATCH 03/85] Updated version number for this branch --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ebbfcc5..217d870 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ These are sample code files to accompany the book “Interactive Data Visualizat ### Version -**Important:** Make sure you are using the correct version of these example files! Otherwise, the examples you see here may not exactly match the ones you see in the book. +**Important:** Make sure you are using the correct version of these sample files! Otherwise, the samples you see here may not exactly match the ones you see in the book. -This is version **1.0**. This release matches examples seen in the first edition of the book, published March 2013. +This version is **in progress for the second edition**. You probably don’t want this version, as it will only be of interest to Scott. + +Check [the release page](https://github.com/alignedleft/d3-book/releases) to download version 1.0, which matches code shown in the first edition of the book, published March 2013. From c3e7e001e28fb6ae63b8caed6f89822767630270 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 14 Aug 2015 09:18:21 -0700 Subject: [PATCH 04/85] Replaced fixed values with variables --- chapter_06/10_drawing_svgs_circles.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chapter_06/10_drawing_svgs_circles.html b/chapter_06/10_drawing_svgs_circles.html index 9d14d31..ee4cea3 100644 --- a/chapter_06/10_drawing_svgs_circles.html +++ b/chapter_06/10_drawing_svgs_circles.html @@ -21,8 +21,8 @@ //Create SVG element var svg = d3.select("body") .append("svg") - .attr("width", 500) - .attr("height", 50); + .attr("width", w) + .attr("height", h); var circles = svg.selectAll("circle") .data(dataset) From 8278aeb4f4b4b65916080056d3933b3d00d809de Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 10 Mar 2016 11:07:17 -0800 Subject: [PATCH 05/85] Test commit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 217d870..4937681 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,5 @@ These are sample code files to accompany the book “Interactive Data Visualizat This version is **in progress for the second edition**. You probably don’t want this version, as it will only be of interest to Scott. Check [the release page](https://github.com/alignedleft/d3-book/releases) to download version 1.0, which matches code shown in the first edition of the book, published March 2013. + +Test; disregard. \ No newline at end of file From 00db0e1ebe5032abb8b25017088554be25a36bda Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 10 Mar 2016 11:08:22 -0800 Subject: [PATCH 06/85] Revert test commit --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 4937681..217d870 100644 --- a/README.md +++ b/README.md @@ -15,5 +15,3 @@ These are sample code files to accompany the book “Interactive Data Visualizat This version is **in progress for the second edition**. You probably don’t want this version, as it will only be of interest to Scott. Check [the release page](https://github.com/alignedleft/d3-book/releases) to download version 1.0, which matches code shown in the first edition of the book, published March 2013. - -Test; disregard. \ No newline at end of file From f81c1f05a1f62eae1b3bf86895261b17d11b5211 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 10 Mar 2016 14:51:06 -0800 Subject: [PATCH 07/85] Test commit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 217d870..bf6b5f6 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,5 @@ These are sample code files to accompany the book “Interactive Data Visualizat This version is **in progress for the second edition**. You probably don’t want this version, as it will only be of interest to Scott. Check [the release page](https://github.com/alignedleft/d3-book/releases) to download version 1.0, which matches code shown in the first edition of the book, published March 2013. + +Test commit \ No newline at end of file From e33652080456132226021d38cb1cac2fa4f68b72 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 10 Mar 2016 14:51:26 -0800 Subject: [PATCH 08/85] Undo test commit --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index bf6b5f6..217d870 100644 --- a/README.md +++ b/README.md @@ -15,5 +15,3 @@ These are sample code files to accompany the book “Interactive Data Visualizat This version is **in progress for the second edition**. You probably don’t want this version, as it will only be of interest to Scott. Check [the release page](https://github.com/alignedleft/d3-book/releases) to download version 1.0, which matches code shown in the first edition of the book, published March 2013. - -Test commit \ No newline at end of file From 64bccf4fdaa1c232c447497e9cb32042690e7f6c Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 21 Nov 2016 12:36:22 -0800 Subject: [PATCH 09/85] Updated D3 to v4.3.0 --- d3/d3.v3.js | 7801 ------------------------ d3/d3.v4.js | 16383 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 16383 insertions(+), 7801 deletions(-) delete mode 100644 d3/d3.v3.js create mode 100644 d3/d3.v4.js diff --git a/d3/d3.v3.js b/d3/d3.v3.js deleted file mode 100644 index 24904eb..0000000 --- a/d3/d3.v3.js +++ /dev/null @@ -1,7801 +0,0 @@ -d3 = function() { - var π = Math.PI, ε = 1e-6, d3 = { - version: "3.0.8" - }, d3_radians = π / 180, d3_degrees = 180 / π, d3_document = document, d3_window = window; - function d3_target(d) { - return d.target; - } - function d3_source(d) { - return d.source; - } - var d3_format_decimalPoint = ".", d3_format_thousandsSeparator = ",", d3_format_grouping = [ 3, 3 ]; - if (!Date.now) Date.now = function() { - return +new Date(); - }; - try { - d3_document.createElement("div").style.setProperty("opacity", 0, ""); - } catch (error) { - var d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; - d3_style_prototype.setProperty = function(name, value, priority) { - d3_style_setProperty.call(this, name, value + "", priority); - }; - } - function d3_class(ctor, properties) { - try { - for (var key in properties) { - Object.defineProperty(ctor.prototype, key, { - value: properties[key], - enumerable: false - }); - } - } catch (e) { - ctor.prototype = properties; - } - } - var d3_array = d3_arraySlice; - function d3_arrayCopy(pseudoarray) { - var i = -1, n = pseudoarray.length, array = []; - while (++i < n) array.push(pseudoarray[i]); - return array; - } - function d3_arraySlice(pseudoarray) { - return Array.prototype.slice.call(pseudoarray); - } - try { - d3_array(d3_document.documentElement.childNodes)[0].nodeType; - } catch (e) { - d3_array = d3_arrayCopy; - } - var d3_arraySubclass = [].__proto__ ? function(array, prototype) { - array.__proto__ = prototype; - } : function(array, prototype) { - for (var property in prototype) array[property] = prototype[property]; - }; - d3.map = function(object) { - var map = new d3_Map(); - for (var key in object) map.set(key, object[key]); - return map; - }; - function d3_Map() {} - d3_class(d3_Map, { - has: function(key) { - return d3_map_prefix + key in this; - }, - get: function(key) { - return this[d3_map_prefix + key]; - }, - set: function(key, value) { - return this[d3_map_prefix + key] = value; - }, - remove: function(key) { - key = d3_map_prefix + key; - return key in this && delete this[key]; - }, - keys: function() { - var keys = []; - this.forEach(function(key) { - keys.push(key); - }); - return keys; - }, - values: function() { - var values = []; - this.forEach(function(key, value) { - values.push(value); - }); - return values; - }, - entries: function() { - var entries = []; - this.forEach(function(key, value) { - entries.push({ - key: key, - value: value - }); - }); - return entries; - }, - forEach: function(f) { - for (var key in this) { - if (key.charCodeAt(0) === d3_map_prefixCode) { - f.call(this, key.substring(1), this[key]); - } - } - } - }); - var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0); - function d3_identity(d) { - return d; - } - function d3_true() { - return true; - } - function d3_functor(v) { - return typeof v === "function" ? v : function() { - return v; - }; - } - d3.functor = d3_functor; - 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; - }; - } - d3.ascending = function(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.mean = function(array, f) { - var n = array.length, a, m = 0, i = -1, j = 0; - if (arguments.length === 1) { - while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j; - } else { - while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j; - } - return j ? m : undefined; - }; - d3.median = function(array, f) { - if (arguments.length > 1) array = array.map(f); - array = array.filter(d3_number); - return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined; - }; - d3.min = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; - 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 && ((a = array[i]) == null || a != a)) a = undefined; - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; - 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 && ((a = c = array[i]) == null || a != a)) a = c = undefined; - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined; - 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 ]; - }; - 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()); - }; - }, - irwinHall: function(m) { - return function() { - for (var s = 0, j = 0; j < m; j++) s += Math.random(); - return s / m; - }; - } - }; - function d3_number(x) { - return x != null && !isNaN(x); - } - d3.sum = function(array, f) { - var s = 0, n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (!isNaN(a = +array[i])) s += a; - } else { - while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a; - } - return s; - }; - 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.shuffle = function(array) { - var m = array.length, t, i; - while (m) { - i = Math.random() * m-- | 0; - t = array[m], array[m] = array[i], array[i] = t; - } - return array; - }; - d3.transpose = function(matrix) { - return d3.zip.apply(d3, matrix); - }; - 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.bisector = function(f) { - 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 (f.call(a, a[mid], mid) < x) 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 (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1; - } - return lo; - } - }; - }; - var d3_bisector = d3.bisector(function(d) { - return d; - }); - d3.bisectLeft = d3_bisector.left; - d3.bisect = d3.bisectRight = d3_bisector.right; - d3.nest = function() { - var nest = {}, keys = [], sortKeys = [], sortValues, rollup; - function map(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, valuesByKey = new d3_Map(), values, o = {}; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(object = array[i]))) { - values.push(object); - } else { - valuesByKey.set(keyValue, [ object ]); - } - } - valuesByKey.forEach(function(keyValue, values) { - o[keyValue] = map(values, depth); - }); - return o; - } - function entries(map, depth) { - if (depth >= keys.length) return map; - var a = [], sortKey = sortKeys[depth++], key; - for (key in map) { - a.push({ - key: key, - values: entries(map[key], depth) - }); - } - if (sortKey) a.sort(function(a, b) { - return sortKey(a.key, b.key); - }); - return a; - } - nest.map = function(array) { - return map(array, 0); - }; - nest.entries = function(array) { - return entries(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.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.permute = function(array, indexes) { - var permutes = [], i = -1, n = indexes.length; - while (++i < n) permutes[i] = array[indexes[i]]; - return permutes; - }; - d3.merge = function(arrays) { - return Array.prototype.concat.apply([], arrays); - }; - function d3_collapse(s) { - return s.trim().replace(/\s+/g, " "); - } - 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(Math.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; - } - d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); - }; - var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - d3.round = function(x, n) { - return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); - }; - d3.xhr = function(url, mimeType, callback) { - var xhr = {}, dispatch = d3.dispatch("progress", "load", "error"), headers = {}, response = d3_identity, request = new (d3_window.XDomainRequest && /^(http(s)?:)?\/\//.test(url) ? XDomainRequest : XMLHttpRequest)(); - "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { - request.readyState > 3 && respond(); - }; - function respond() { - var s = request.status; - !s && request.responseText || s >= 200 && s < 300 || s === 304 ? dispatch.load.call(xhr, response.call(xhr, request)) : dispatch.error.call(xhr, request); - } - 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.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 (callback != null) xhr.on("error", callback).on("load", function(request) { - callback(null, request); - }); - request.send(data == null ? null : data); - return xhr; - }; - xhr.abort = function() { - request.abort(); - return xhr; - }; - d3.rebind(xhr, dispatch, "on"); - if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, - mimeType = null; - return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); - }; - function d3_xhr_fixCallback(callback) { - return callback.length === 1 ? function(error, request) { - callback(error == null ? request : null); - } : callback; - } - d3.text = function() { - return d3.xhr.apply(d3, arguments).response(d3_text); - }; - function d3_text(request) { - return request.responseText; - } - d3.json = function(url, callback) { - return d3.xhr(url, "application/json", callback).response(d3_json); - }; - function d3_json(request) { - return JSON.parse(request.responseText); - } - d3.html = function(url, callback) { - return d3.xhr(url, "text/html", callback).response(d3_html); - }; - function d3_html(request) { - var range = d3_document.createRange(); - range.selectNode(d3_document.body); - return range.createContextualFragment(request.responseText); - } - d3.xml = function() { - return d3.xhr.apply(d3, arguments).response(d3_xml); - }; - function d3_xml(request) { - return request.responseXML; - } - 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.substring(0, i); - name = name.substring(i + 1); - } - return d3_nsPrefix.hasOwnProperty(prefix) ? { - space: d3_nsPrefix[prefix], - local: name - } : name; - } - }; - 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.substring(i + 1); - type = type.substring(0, i); - } - return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); - }; - 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.format = function(specifier) { - var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", basePrefix = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false; - if (precision) precision = +precision.substring(1); - if (zfill || fill === "0" && align === "=") { - zfill = fill = "0"; - align = "="; - if (comma) width -= Math.floor((width - 1) / 4); - } - 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 (basePrefix) basePrefix = "0" + type.toLowerCase(); - - case "c": - case "d": - integer = true; - precision = 0; - break; - - case "s": - scale = -1; - type = "r"; - break; - } - if (basePrefix === "#") basePrefix = ""; - if (type == "r" && !precision) type = "g"; - type = d3_format_types.get(type) || d3_format_typeDefault; - var zcomma = zfill && comma; - return function(value) { - if (integer && value % 1) return ""; - var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign; - if (scale < 0) { - var prefix = d3.formatPrefix(value, precision); - value = prefix.scale(value); - suffix = prefix.symbol; - } else { - value *= scale; - } - value = type(value, precision); - if (!zfill && comma) value = d3_format_group(value); - var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; - if (zcomma) value = d3_format_group(padding + value); - if (d3_format_decimalPoint) value.replace(".", d3_format_decimalPoint); - negative += basePrefix; - 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)) + suffix; - }; - }; - var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/; - 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)))); - } - }); - function d3_format_precision(x, p) { - return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); - } - function d3_format_typeDefault(x) { - return x + ""; - } - var d3_format_group = d3_identity; - if (d3_format_grouping) { - var d3_format_groupingLength = d3_format_grouping.length; - d3_format_group = function(value) { - var i = value.lastIndexOf("."), f = i >= 0 ? "." + value.substring(i + 1) : (i = value.length, - ""), t = [], j = 0, g = d3_format_grouping[0]; - while (i > 0 && g > 0) { - t.push(value.substring(i -= g, i + g)); - g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength]; - } - return t.reverse().join(d3_format_thousandsSeparator || "") + f; - }; - } - 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 <= 0 ? i + 1 : i - 1) / 3) * 3)); - } - return d3_formatPrefixes[8 + i / 3]; - }; - function d3_formatPrefix(d, i) { - var k = Math.pow(10, Math.abs(8 - i) * 3); - return { - scale: i > 8 ? function(d) { - return d / k; - } : function(d) { - return d * k; - }, - symbol: d - }; - } - 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; - }, - 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.substring(0, i) : name, m = i >= 0 ? name.substring(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, Array.prototype.slice.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_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); - }; - } - 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_ease_poly(e) { - return function(t) { - return Math.pow(t, e); - }; - } - function d3_ease_sin(t) { - return 1 - Math.cos(t * π / 2); - } - 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 / (2 * π) * 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) * 2 * π / 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.event = null; - function d3_eventCancel() { - d3.event.stopPropagation(); - 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.transform = function(string) { - var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); - return (d3.transform = function(string) { - 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; - } - 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 k; - } - 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 - }; - d3.interpolate = function(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; - return f; - }; - d3.interpolateNumber = function(a, b) { - b -= a; - return function(t) { - return a + b * t; - }; - }; - d3.interpolateRound = function(a, b) { - b -= a; - return function(t) { - return Math.round(a + b * t); - }; - }; - d3.interpolateString = function(a, b) { - var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o; - d3_interpolate_number.lastIndex = 0; - for (i = 0; m = d3_interpolate_number.exec(b); ++i) { - if (m.index) s.push(b.substring(s0, s1 = m.index)); - q.push({ - i: s.length, - x: m[0] - }); - s.push(null); - s0 = d3_interpolate_number.lastIndex; - } - if (s0 < b.length) s.push(b.substring(s0)); - for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) { - o = q[i]; - if (o.x == m[0]) { - if (o.i) { - if (s[o.i + 1] == null) { - s[o.i - 1] += o.x; - s.splice(o.i, 1); - for (j = i + 1; j < n; ++j) q[j].i--; - } else { - s[o.i - 1] += o.x + s[o.i + 1]; - s.splice(o.i, 2); - for (j = i + 1; j < n; ++j) q[j].i -= 2; - } - } else { - if (s[o.i + 1] == null) { - s[o.i] = o.x; - } else { - s[o.i] = o.x + s[o.i + 1]; - s.splice(o.i + 1, 1); - for (j = i + 1; j < n; ++j) q[j].i--; - } - } - q.splice(i, 1); - n--; - i--; - } else { - o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x)); - } - } - while (i < n) { - o = q.pop(); - if (s[o.i + 1] == null) { - s[o.i] = o.x; - } else { - s[o.i] = o.x + s[o.i + 1]; - s.splice(o.i + 1, 1); - } - n--; - } - if (s.length === 1) { - return s[0] == null ? q[0].x : function() { - return b; - }; - } - return function(t) { - for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - }; - d3.interpolateTransform = function(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(""); - } - 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 + ")"); - } - 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 + ")"); - } - 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 + ")"); - } - n = q.length; - return function(t) { - var i = -1, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - }; - d3.interpolateRgb = function(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.interpolateHsl = function(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var h0 = a.h, s0 = a.s, l0 = a.l, h1 = b.h - h0, s1 = b.s - s0, l1 = b.l - l0; - if (h1 > 180) h1 -= 360; else if (h1 < -180) h1 += 360; - return function(t) { - return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t) + ""; - }; - }; - d3.interpolateLab = function(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.interpolateHcl = function(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 (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.interpolateArray = function(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.interpolateObject = function(a, b) { - var i = {}, c = {}, k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolateByName(k)(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; - }; - }; - var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; - function d3_interpolateByName(name) { - return name == "transform" ? d3.interpolateTransform : d3.interpolate; - } - d3.interpolators = [ d3.interpolateObject, function(a, b) { - return b instanceof Array && d3.interpolateArray(a, b); - }, function(a, b) { - return (typeof a === "string" || typeof b === "string") && d3.interpolateString(a + "", b + ""); - }, function(a, b) { - return (typeof b === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Color) && d3.interpolateRgb(a, b); - }, function(a, b) { - return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b); - } ]; - function d3_uninterpolateNumber(a, b) { - b = b - (a = +a) ? 1 / (b - a) : 0; - return function(x) { - return (x - a) * b; - }; - } - function d3_uninterpolateClamp(a, b) { - b = b - (a = +a) ? 1 / (b - a) : 0; - return function(x) { - return Math.max(0, Math.min(1, (x - a) * b)); - }; - } - function d3_Color() {} - d3_Color.prototype.toString = function() { - return this.rgb() + ""; - }; - d3.rgb = function(r, g, b) { - return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b); - }; - function d3_rgb(r, g, b) { - return new d3_Rgb(r, g, b); - } - function d3_Rgb(r, g, b) { - this.r = r; - this.g = g; - this.b = b; - } - 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 d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k))); - }; - d3_rgbPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(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, name; - m1 = /([a-z]+)\((.*)\)/i.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])); - } - } - } - if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b); - if (format != null && format.charAt(0) === "#") { - if (format.length === 4) { - r = format.charAt(1); - r += r; - g = format.charAt(2); - g += g; - b = format.charAt(3); - b += b; - } else if (format.length === 7) { - r = format.substring(1, 3); - g = format.substring(3, 5); - b = format.substring(5, 7); - } - r = parseInt(r, 16); - g = parseInt(g, 16); - b = parseInt(b, 16); - } - 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 { - s = h = 0; - } - return 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: "#f0f8ff", - antiquewhite: "#faebd7", - aqua: "#00ffff", - aquamarine: "#7fffd4", - azure: "#f0ffff", - beige: "#f5f5dc", - bisque: "#ffe4c4", - black: "#000000", - blanchedalmond: "#ffebcd", - blue: "#0000ff", - blueviolet: "#8a2be2", - brown: "#a52a2a", - burlywood: "#deb887", - cadetblue: "#5f9ea0", - chartreuse: "#7fff00", - chocolate: "#d2691e", - coral: "#ff7f50", - cornflowerblue: "#6495ed", - cornsilk: "#fff8dc", - crimson: "#dc143c", - cyan: "#00ffff", - darkblue: "#00008b", - darkcyan: "#008b8b", - darkgoldenrod: "#b8860b", - darkgray: "#a9a9a9", - darkgreen: "#006400", - darkgrey: "#a9a9a9", - darkkhaki: "#bdb76b", - darkmagenta: "#8b008b", - darkolivegreen: "#556b2f", - darkorange: "#ff8c00", - darkorchid: "#9932cc", - darkred: "#8b0000", - darksalmon: "#e9967a", - darkseagreen: "#8fbc8f", - darkslateblue: "#483d8b", - darkslategray: "#2f4f4f", - darkslategrey: "#2f4f4f", - darkturquoise: "#00ced1", - darkviolet: "#9400d3", - deeppink: "#ff1493", - deepskyblue: "#00bfff", - dimgray: "#696969", - dimgrey: "#696969", - dodgerblue: "#1e90ff", - firebrick: "#b22222", - floralwhite: "#fffaf0", - forestgreen: "#228b22", - fuchsia: "#ff00ff", - gainsboro: "#dcdcdc", - ghostwhite: "#f8f8ff", - gold: "#ffd700", - goldenrod: "#daa520", - gray: "#808080", - green: "#008000", - greenyellow: "#adff2f", - grey: "#808080", - honeydew: "#f0fff0", - hotpink: "#ff69b4", - indianred: "#cd5c5c", - indigo: "#4b0082", - ivory: "#fffff0", - khaki: "#f0e68c", - lavender: "#e6e6fa", - lavenderblush: "#fff0f5", - lawngreen: "#7cfc00", - lemonchiffon: "#fffacd", - lightblue: "#add8e6", - lightcoral: "#f08080", - lightcyan: "#e0ffff", - lightgoldenrodyellow: "#fafad2", - lightgray: "#d3d3d3", - lightgreen: "#90ee90", - lightgrey: "#d3d3d3", - lightpink: "#ffb6c1", - lightsalmon: "#ffa07a", - lightseagreen: "#20b2aa", - lightskyblue: "#87cefa", - lightslategray: "#778899", - lightslategrey: "#778899", - lightsteelblue: "#b0c4de", - lightyellow: "#ffffe0", - lime: "#00ff00", - limegreen: "#32cd32", - linen: "#faf0e6", - magenta: "#ff00ff", - maroon: "#800000", - mediumaquamarine: "#66cdaa", - mediumblue: "#0000cd", - mediumorchid: "#ba55d3", - mediumpurple: "#9370db", - mediumseagreen: "#3cb371", - mediumslateblue: "#7b68ee", - mediumspringgreen: "#00fa9a", - mediumturquoise: "#48d1cc", - mediumvioletred: "#c71585", - midnightblue: "#191970", - mintcream: "#f5fffa", - mistyrose: "#ffe4e1", - moccasin: "#ffe4b5", - navajowhite: "#ffdead", - navy: "#000080", - oldlace: "#fdf5e6", - olive: "#808000", - olivedrab: "#6b8e23", - orange: "#ffa500", - orangered: "#ff4500", - orchid: "#da70d6", - palegoldenrod: "#eee8aa", - palegreen: "#98fb98", - paleturquoise: "#afeeee", - palevioletred: "#db7093", - papayawhip: "#ffefd5", - peachpuff: "#ffdab9", - peru: "#cd853f", - pink: "#ffc0cb", - plum: "#dda0dd", - powderblue: "#b0e0e6", - purple: "#800080", - red: "#ff0000", - rosybrown: "#bc8f8f", - royalblue: "#4169e1", - saddlebrown: "#8b4513", - salmon: "#fa8072", - sandybrown: "#f4a460", - seagreen: "#2e8b57", - seashell: "#fff5ee", - sienna: "#a0522d", - silver: "#c0c0c0", - skyblue: "#87ceeb", - slateblue: "#6a5acd", - slategray: "#708090", - slategrey: "#708090", - snow: "#fffafa", - springgreen: "#00ff7f", - steelblue: "#4682b4", - tan: "#d2b48c", - teal: "#008080", - thistle: "#d8bfd8", - tomato: "#ff6347", - turquoise: "#40e0d0", - violet: "#ee82ee", - wheat: "#f5deb3", - white: "#ffffff", - whitesmoke: "#f5f5f5", - yellow: "#ffff00", - yellowgreen: "#9acd32" - }); - d3_rgb_names.forEach(function(key, value) { - d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb)); - }); - d3.hsl = function(h, s, l) { - return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l); - }; - function d3_hsl(h, s, l) { - return new d3_Hsl(h, s, l); - } - function d3_Hsl(h, s, l) { - this.h = h; - this.s = s; - this.l = l; - } - var d3_hslPrototype = d3_Hsl.prototype = new d3_Color(); - d3_hslPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return d3_hsl(this.h, this.s, this.l / k); - }; - d3_hslPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return 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 = h % 360; - if (h < 0) h += 360; - s = 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 d3_rgb(vv(h + 120), vv(h), vv(h - 120)); - } - d3.hcl = function(h, c, l) { - return arguments.length === 1 ? h instanceof d3_Hcl ? 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) : d3_hcl(+h, +c, +l); - }; - function d3_hcl(h, c, l) { - return new d3_Hcl(h, c, l); - } - function d3_Hcl(h, c, l) { - this.h = h; - this.c = c; - this.l = l; - } - var d3_hclPrototype = d3_Hcl.prototype = new d3_Color(); - d3_hclPrototype.brighter = function(k) { - return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.darker = function(k) { - return 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) { - return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); - } - d3.lab = function(l, a, b) { - return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b); - }; - function d3_lab(l, a, b) { - return new d3_Lab(l, a, b); - } - function d3_Lab(l, a, b) { - this.l = l; - this.a = a; - this.b = 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 d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.darker = function(k) { - return 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 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 d3_hcl(Math.atan2(b, a) / π * 180, Math.sqrt(a * a + b * b), 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)); - } - function d3_selection(groups) { - d3_arraySubclass(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_selectRoot = d3_document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) { - return d3_selectMatcher.call(n, s); - }; - if (typeof Sizzle === "function") { - d3_select = function(s, n) { - return Sizzle(s, n)[0] || null; - }; - d3_selectAll = function(s, n) { - return Sizzle.uniqueSort(Sizzle(s, n)); - }; - d3_selectMatches = Sizzle.matchesSelector; - } - var d3_selectionPrototype = []; - d3.selection = function() { - return d3_selectionRoot; - }; - d3.selection.prototype = d3_selectionPrototype; - d3_selectionPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, group, node; - if (typeof selector !== "function") 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)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selector(selector) { - return function() { - return d3_select(selector, this); - }; - } - d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], subgroup, node; - if (typeof selector !== "function") 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))); - subgroup.parentNode = node; - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selectorAll(selector) { - return function() { - return d3_selectAll(selector, this); - }; - } - 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; - } - d3_selectionPrototype.classed = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1; - if (value = node.classList) { - while (++i < n) if (!value.contains(name[i])) return false; - } else { - value = node.className; - if (value.baseVal != null) value = value.baseVal; - 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_classed(name, value) { - name = name.trim().split(/\s+/).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.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c; - if (value) { - re.lastIndex = 0; - if (!re.test(cv)) { - cv = d3_collapse(cv + " " + name); - if (cb) c.baseVal = cv; else node.className = cv; - } - } else if (cv) { - cv = d3_collapse(cv.replace(re, " ")); - if (cb) c.baseVal = cv; else node.className = cv; - } - }; - } - 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) return d3_window.getComputedStyle(this.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.ns.qualify(name); - function append() { - return this.appendChild(d3_document.createElementNS(this.namespaceURI, name)); - } - function appendNS() { - return this.appendChild(d3_document.createElementNS(name.space, name.local)); - } - return this.select(name.local ? appendNS : append); - }; - d3_selectionPrototype.insert = function(name, before) { - name = d3.ns.qualify(name); - function insert() { - return this.insertBefore(d3_document.createElementNS(this.namespaceURI, name), d3_select(before, this)); - } - function insertNS() { - return this.insertBefore(d3_document.createElementNS(name.space, name.local), d3_select(before, this)); - } - return this.select(name.local ? insertNS : insert); - }; - d3_selectionPrototype.remove = function() { - return this.each(function() { - 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(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue; - for (i = -1; ++i < n; ) { - keyValue = key.call(node = group[i], node.__data__, i); - if (nodeByKeyValue.has(keyValue)) { - exitNodes[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - keyValues.push(keyValue); - } - for (i = -1; ++i < m; ) { - keyValue = key.call(groupData, nodeData = groupData[i], i); - if (node = nodeByKeyValue.get(keyValue)) { - updateNodes[i] = node; - node.__data__ = nodeData; - } else if (!dataByKeyValue.has(keyValue)) { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - dataByKeyValue.set(keyValue, nodeData); - nodeByKeyValue.remove(keyValue); - } - for (i = -1; ++i < n; ) { - if (nodeByKeyValue.has(keyValues[i])) { - 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)) { - 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__); - }; - } - 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("."); - if (i > 0) type = type.substring(0, i); - function onRemove() { - var wrapper = this[name]; - if (wrapper) { - this.removeEventListener(type, wrapper, wrapper.$); - delete this[name]; - } - } - function onAdd() { - var node = this, args = d3_array(arguments); - onRemove.call(this); - this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture); - wrapper._ = listener; - function wrapper(e) { - var o = d3.event; - d3.event = e; - args[0] = node.__data__; - try { - listener.apply(node, args); - } finally { - d3.event = o; - } - } - } - return listener ? onAdd : onRemove; - } - 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.transition = function() { - var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit); - transition.time = Date.now(); - 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, id, transition); - subgroup.push(node); - } - } - return d3_transition(subgroups, id); - }; - var d3_selectionRoot = d3_selection([ [ d3_document ] ]); - d3_selectionRoot[0].parentNode = d3_selectRoot; - d3.select = function(selector) { - return typeof selector === "string" ? d3_selectionRoot.select(selector) : d3_selection([ [ selector ] ]); - }; - d3.selectAll = function(selector) { - return typeof selector === "string" ? d3_selectionRoot.selectAll(selector) : d3_selection([ d3_array(selector) ]); - }; - function d3_selection_enter(selection) { - d3_arraySubclass(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.insert = d3_selectionPrototype.insert; - d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; - d3_selection_enterPrototype.node = d3_selectionPrototype.node; - 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)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_transition(groups, id) { - d3_arraySubclass(groups, d3_transitionPrototype); - groups.id = id; - return groups; - } - var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit = { - ease: d3_ease_cubicInOut, - delay: 0, - duration: 250 - }; - d3_transitionPrototype.call = d3_selectionPrototype.call; - d3_transitionPrototype.empty = d3_selectionPrototype.empty; - d3_transitionPrototype.node = d3_selectionPrototype.node; - d3.transition = function(selection) { - return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition(); - }; - d3.transition.prototype = d3_transitionPrototype; - function d3_transitionNode(node, i, id, inherit) { - var lock = node.__transition__ || (node.__transition__ = { - active: 0, - count: 0 - }), transition = lock[id]; - if (!transition) { - var time = inherit.time; - transition = lock[id] = { - tween: new d3_Map(), - event: d3.dispatch("start", "end"), - time: time, - ease: inherit.ease, - delay: inherit.delay, - duration: inherit.duration - }; - ++lock.count; - d3.timer(function(elapsed) { - var d = node.__data__, ease = transition.ease, event = transition.event, delay = transition.delay, duration = transition.duration, tweened = []; - return delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time), 1; - function start(elapsed) { - if (lock.active > id) return stop(); - lock.active = id; - event.start.call(node, d, i); - transition.tween.forEach(function(key, value) { - if (value = value.call(node, d, i)) { - tweened.push(value); - } - }); - if (!tick(elapsed)) d3.timer(tick, 0, time); - return 1; - } - function tick(elapsed) { - if (lock.active !== id) return stop(); - var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length; - while (n > 0) { - tweened[--n].call(node, e); - } - if (t >= 1) { - stop(); - event.end.call(node, d, i); - return 1; - } - } - function stop() { - if (--lock.count) delete lock[id]; else delete node.__transition__; - return 1; - } - }, 0, time); - return transition; - } - } - d3_transitionPrototype.select = function(selector) { - var id = this.id, subgroups = [], subgroup, subnode, node; - if (typeof selector !== "function") 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))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - d3_transitionNode(subnode, i, id, node.__transition__[id]); - subgroup.push(subnode); - } else { - subgroup.push(null); - } - } - } - return d3_transition(subgroups, id); - }; - d3_transitionPrototype.selectAll = function(selector) { - var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition; - if (typeof selector !== "function") 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.__transition__[id]; - subnodes = selector.call(node, node.__data__, i); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o; ) { - d3_transitionNode(subnode = subnodes[k], k, id, transition); - subgroup.push(subnode); - } - } - } - } - return d3_transition(subgroups, id); - }; - 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)) { - subgroup.push(node); - } - } - } - return d3_transition(subgroups, this.id, this.time).ease(this.ease()); - }; - d3_transitionPrototype.attr = function(nameNS, value) { - if (arguments.length < 2) { - for (value in nameNS) this.attr(value, nameNS[value]); - return this; - } - var interpolate = d3_interpolateByName(nameNS), name = d3.ns.qualify(nameNS); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - return d3_transition_tween(this, "attr." + nameNS, value, function(b) { - function attrString() { - var a = this.getAttribute(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttribute(name, i(t)); - }); - } - function attrStringNS() { - 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)); - }); - } - return b == null ? name.local ? attrNullNS : attrNull : (b += "", name.local ? attrStringNS : attrString); - }); - }; - 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)); - }; - } - 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 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 = ""; - } - var interpolate = d3_interpolateByName(name); - function styleNull() { - this.style.removeProperty(name); - } - return d3_transition_tween(this, "style." + name, value, function(b) { - function styleString() { - var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.style.setProperty(name, i(t), priority); - }); - } - return b == null ? styleNull : (b += "", styleString); - }); - }; - d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - return this.tween("style." + name, function(d, i) { - var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name)); - return f && function(t) { - this.style.setProperty(name, f(t), priority); - }; - }); - }; - 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; - }; - } - d3_transitionPrototype.remove = function() { - return this.each("end.transition", function() { - var p; - if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this); - }); - }; - d3_transitionPrototype.ease = function(value) { - var id = this.id; - if (arguments.length < 1) return this.node().__transition__[id].ease; - if (typeof value !== "function") value = d3.ease.apply(d3, arguments); - return d3_selection_each(this, function(node) { - node.__transition__[id].ease = value; - }); - }; - d3_transitionPrototype.delay = function(value) { - var id = this.id; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node.__transition__[id].delay = value.call(node, node.__data__, i, j) | 0; - } : (value |= 0, function(node) { - node.__transition__[id].delay = value; - })); - }; - d3_transitionPrototype.duration = function(value) { - var id = this.id; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j) | 0); - } : (value = Math.max(1, value | 0), function(node) { - node.__transition__[id].duration = value; - })); - }; - d3_transitionPrototype.each = function(type, listener) { - var id = this.id; - if (arguments.length < 2) { - var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; - d3_transitionInheritId = id; - d3_selection_each(this, function(node, i, j) { - d3_transitionInherit = node.__transition__[id]; - type.call(node, node.__data__, i, j); - }); - d3_transitionInherit = inherit; - d3_transitionInheritId = inheritId; - } else { - d3_selection_each(this, function(node) { - node.__transition__[id].event.on(type, listener); - }); - } - return this; - }; - d3_transitionPrototype.transition = function() { - var id0 = this.id, id1 = ++d3_transitionId, 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 = Object.create(node.__transition__[id0]); - transition.delay += transition.duration; - d3_transitionNode(node, i, id1, transition); - } - subgroup.push(node); - } - } - return d3_transition(subgroups, id1); - }; - d3_transitionPrototype.tween = function(name, tween) { - var id = this.id; - if (arguments.length < 2) return this.node().__transition__[id].tween.get(name); - return d3_selection_each(this, tween == null ? function(node) { - node.__transition__[id].tween.remove(name); - } : function(node) { - node.__transition__[id].tween.set(name, tween); - }); - }; - function d3_transition_tween(groups, name, value, tween) { - var id = groups.id; - return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { - node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j))); - } : (value = tween(value), function(node) { - node.__transition__[id].tween.set(name, value); - })); - } - var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout; - d3.timer = function(callback, delay, then) { - if (arguments.length < 3) { - if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return; - then = Date.now(); - } - var timer = d3_timer_byId[callback.id]; - if (timer && timer.callback === callback) { - timer.then = then; - timer.delay = delay; - } else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = { - callback: callback, - then: then, - delay: delay, - next: d3_timer_queue - }; - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - }; - function d3_timer_step() { - var elapsed, now = Date.now(), t1 = d3_timer_queue; - while (t1) { - elapsed = now - t1.then; - if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed); - t1 = t1.next; - } - var delay = d3_timer_flush() - 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); - } - } - d3.timer.flush = function() { - var elapsed, now = Date.now(), t1 = d3_timer_queue; - while (t1) { - elapsed = now - t1.then; - if (!t1.delay) t1.flush = t1.callback(elapsed); - t1 = t1.next; - } - d3_timer_flush(); - }; - function d3_timer_flush() { - var t0 = null, t1 = d3_timer_queue, then = Infinity; - while (t1) { - if (t1.flush) { - delete d3_timer_byId[t1.callback.id]; - t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next; - } else { - then = Math.min(then, t1.then + t1.delay); - t1 = (t0 = t1).next; - } - } - return then; - } - var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) { - setTimeout(callback, 17); - }; - d3.mouse = function(container) { - return d3_mousePoint(container, d3_eventSource()); - }; - var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0; - function d3_mousePoint(container, e) { - var svg = container.ownerSVGElement || container; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) { - svg = d3.select(d3_document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0); - 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.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_noop() {} - 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_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; - } - if (nice = nice(x1 - x0)) { - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - } - return domain; - } - function d3_scale_niceDefault() { - return Math; - } - 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; - } - function scale(x) { - return output(x); - } - scale.invert = function(y) { - return input(y); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3.interpolateRound); - }; - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); - }; - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m) { - return d3_scale_linearTickFormat(domain, m); - }; - scale.nice = function() { - d3_scale_nice(domain, d3_scale_linearNice); - return rescale(); - }; - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); - }; - return rescale(); - } - function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_scale_linearNice(dx) { - dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1); - return dx && { - floor: function(x) { - return Math.floor(x / dx) * dx; - }, - ceil: function(x) { - return Math.ceil(x / dx) * dx; - } - }; - } - function d3_scale_linearTickRange(domain, m) { - 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) { - return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f"); - } - 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_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(); - } - while (++j <= k) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); - } - return function(x) { - var j = d3.bisect(domain, x, 1, k) - 1; - return i[j](u[j](x)); - }; - } - d3.scale.log = function() { - return d3_scale_log(d3.scale.linear(), d3_scale_logp); - }; - function d3_scale_log(linear, log) { - var pow = log.pow; - function scale(x) { - return linear(log(x)); - } - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(pow); - log = x[0] < 0 ? d3_scale_logn : d3_scale_logp; - pow = log.pow; - linear.domain(x.map(log)); - return scale; - }; - scale.nice = function() { - linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault)); - return scale; - }; - scale.ticks = function() { - var extent = d3_scaleExtent(linear.domain()), ticks = []; - if (extent.every(isFinite)) { - var i = Math.floor(extent[0]), j = Math.ceil(extent[1]), u = pow(extent[0]), v = pow(extent[1]); - if (log === d3_scale_logn) { - ticks.push(pow(i)); - for (;i++ < j; ) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k); - } else { - for (;i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } - 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 < 2) format = d3_scale_logFormat; - if (!arguments.length) return format; - var k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12, - Math.floor) : (e = 1e-12, Math.ceil), e; - return function(d) { - return d / pow(f(log(d) + e)) <= k ? format(d) : ""; - }; - }; - scale.copy = function() { - return d3_scale_log(linear.copy(), log); - }; - return d3_scale_linearRebind(scale, linear); - } - var d3_scale_logFormat = d3.format(".0e"); - function d3_scale_logp(x) { - return Math.log(x < 0 ? 0 : x) / Math.LN10; - } - function d3_scale_logn(x) { - return -Math.log(x > 0 ? 0 : -x) / Math.LN10; - } - d3_scale_logp.pow = function(x) { - return Math.pow(10, x); - }; - d3_scale_logn.pow = function(x) { - return -Math.pow(10, -x); - }; - d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1); - }; - function d3_scale_pow(linear, exponent) { - 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)); - }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(powb); - linear.domain(x.map(powp)); - return scale; - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(scale.domain(), m); - }; - scale.tickFormat = function(m) { - return d3_scale_linearTickFormat(scale.domain(), m); - }; - scale.nice = function() { - return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice)); - }; - scale.exponent = function(x) { - if (!arguments.length) return exponent; - var domain = scale.domain(); - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - return scale.domain(domain); - }; - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent); - }; - 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.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) || index.set(x, domain.push(x))) - 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); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = { - t: "range", - a: arguments - }; - return scale; - }; - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding); - range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step); - rangeBand = 0; - ranger = { - t: "rangePoints", - a: arguments - }; - 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)), error = stop - start - (domain.length - padding) * step; - range = steps(start + Math.round(error / 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.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 = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ]; - var d3_category20 = [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5" ]; - var d3_category20b = [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" ]; - var d3_category20c = [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9" ]; - d3.scale.quantile = function() { - return d3_scale_quantile([], []); - }; - 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 scale(x) { - if (isNaN(x = +x)) return NaN; - return range[d3.bisect(thresholds, x)]; - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.filter(function(d) { - return !isNaN(d); - }).sort(d3.ascending); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.quantiles = function() { - return thresholds; - }; - 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 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(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); - }; - return rescale(); - } - d3.scale.threshold = function() { - return d3_scale_threshold([ .5 ], [ 0, 1 ]); - }; - function d3_scale_threshold(domain, range) { - function scale(x) { - return range[d3.bisect(domain, x)]; - } - scale.domain = function(_) { - if (!arguments.length) return domain; - domain = _; - return scale; - }; - scale.range = function(_) { - if (!arguments.length) return range; - range = _; - return scale; - }; - scale.copy = function() { - return d3_scale_threshold(domain, range); - }; - 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; - }; - identity.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - identity.tickFormat = function(m) { - return d3_scale_linearTickFormat(domain, m); - }; - identity.copy = function() { - return d3_scale_identity(domain); - }; - return identity; - } - d3.svg = {}; - d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function arc() { - var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, - a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1); - return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z"; - } - 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.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return arc; - }; - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return arc; - }; - arc.centroid = function() { - var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset; - return [ Math.cos(a) * r, Math.sin(a) * r ]; - }; - return arc; - }; - var d3_svg_arcOffset = -π / 2, d3_svg_arcMax = 2 * π - 1e-6; - 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_line(projection) { - var x = d3_svg_lineX, y = d3_svg_lineY, 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 = []; - } - } - if (points.length) segment(); - return segments.length ? segments.join("") : null; - } - 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; - }; - 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; - }; - line.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return line; - }; - return line; - } - d3.svg.line = function() { - return d3_svg_line(d3_identity); - }; - function d3_svg_lineX(d) { - return d[0]; - } - function d3_svg_lineY(d) { - return d[1]; - } - var d3_svg_lineInterpolators = d3.map({ - linear: d3_svg_lineLinear, - "linear-closed": d3_svg_lineLinearClosed, - "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_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, points.length - 1), d3_svg_lineCardinalTangents(points, tension)); - } - 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_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 ]; - d3_svg_lineBasisBezier(path, px, py); - while (++i < n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - i = -1; - while (++i < 2) { - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - 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(""); - } - 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]); - } - 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); - } - 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); - } - } - return d3_svg_lineBasis(points); - } - function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; - } - 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_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); - } - 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; - } - 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 (Math.abs(d) < 1e-6) { - 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; - } - } - } - 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; - } - function d3_svg_lineMonotone(points) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); - } - 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] + d3_svg_arcOffset; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; - } - function d3_svg_area(projection) { - var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, 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"); - } - 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 (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; - }; - area.y = function(_) { - if (!arguments.length) return y1; - y0 = y1 = _; - return area; - }; - area.y0 = function(_) { - if (!arguments.length) return y0; - y0 = _; - return area; - }; - area.y1 = function(_) { - if (!arguments.length) return y1; - y1 = _; - return area; - }; - area.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return area; - }; - 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; - }; - area.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return area; - }; - 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 subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset; - 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) ] - }; - } - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; - } - function arc(r, p, a) { - return "A" + r + "," + r + " 0 " + +(a > π) + ",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; - } - 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]; - } - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3_functor(x); - return diagonal; - }; - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3_functor(x); - return diagonal; - }; - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; - }; - 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; - }; - return diagonal; - }; - function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset; - return [ r * Math.cos(a), r * Math.sin(a) ]; - }; - } - 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; - }; - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3_functor(x); - return symbol; - }; - return symbol; - }; - function d3_svg_symbolSize() { - return 64; - } - function d3_svg_symbolType() { - return "circle"; - } - 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.svg.axis = function() { - var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0; - function axis(g) { - g.each(function() { - var g = d3.select(this); - var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_; - var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(".tick.minor").data(subticks, String), subtickEnter = subtick.enter().insert("line", ".tick").attr("class", "tick minor").style("opacity", 1e-6), subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style("opacity", 1); - var tick = g.selectAll(".tick.major").data(ticks, String), tickEnter = tick.enter().insert("g", "path").attr("class", "tick major").style("opacity", 1e-6), tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform; - var range = d3_scaleRange(scale), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), - d3.transition(path)); - var scale1 = scale.copy(), scale0 = this.__chart__ || scale1; - this.__chart__ = scale1; - 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"); - switch (orient) { - case "bottom": - { - tickTransform = d3_svg_axisX; - subtickEnter.attr("y2", tickMinorSize); - subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize); - lineEnter.attr("y2", tickMajorSize); - textEnter.attr("y", Math.max(tickMajorSize, 0) + tickPadding); - lineUpdate.attr("x2", 0).attr("y2", tickMajorSize); - textUpdate.attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding); - text.attr("dy", ".71em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize); - break; - } - - case "top": - { - tickTransform = d3_svg_axisX; - subtickEnter.attr("y2", -tickMinorSize); - subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize); - lineEnter.attr("y2", -tickMajorSize); - textEnter.attr("y", -(Math.max(tickMajorSize, 0) + tickPadding)); - lineUpdate.attr("x2", 0).attr("y2", -tickMajorSize); - textUpdate.attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding)); - text.attr("dy", "0em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize); - break; - } - - case "left": - { - tickTransform = d3_svg_axisY; - subtickEnter.attr("x2", -tickMinorSize); - subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0); - lineEnter.attr("x2", -tickMajorSize); - textEnter.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)); - lineUpdate.attr("x2", -tickMajorSize).attr("y2", 0); - textUpdate.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0); - text.attr("dy", ".32em").style("text-anchor", "end"); - pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize); - break; - } - - case "right": - { - tickTransform = d3_svg_axisY; - subtickEnter.attr("x2", tickMinorSize); - subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0); - lineEnter.attr("x2", tickMajorSize); - textEnter.attr("x", Math.max(tickMajorSize, 0) + tickPadding); - lineUpdate.attr("x2", tickMajorSize).attr("y2", 0); - textUpdate.attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0); - text.attr("dy", ".32em").style("text-anchor", "start"); - pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize); - break; - } - } - if (scale.ticks) { - tickEnter.call(tickTransform, scale0); - tickUpdate.call(tickTransform, scale1); - tickExit.call(tickTransform, scale1); - subtickEnter.call(tickTransform, scale0); - subtickUpdate.call(tickTransform, scale1); - subtickExit.call(tickTransform, scale1); - } else { - var dx = scale1.rangeBand() / 2, x = function(d) { - return scale1(d) + dx; - }; - tickEnter.call(tickTransform, x); - tickUpdate.call(tickTransform, x); - } - }); - } - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; - }; - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; - return axis; - }; - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = arguments; - return axis; - }; - axis.tickValues = function(x) { - if (!arguments.length) return tickValues; - tickValues = x; - return axis; - }; - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; - }; - axis.tickSize = function(x, y) { - if (!arguments.length) return tickMajorSize; - var n = arguments.length - 1; - tickMajorSize = +x; - tickMinorSize = n > 1 ? +y : tickMajorSize; - tickEndSize = n > 0 ? +arguments[n] : tickMajorSize; - return axis; - }; - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; - }; - axis.tickSubdivide = function(x) { - if (!arguments.length) return tickSubdivide; - tickSubdivide = +x; - return axis; - }; - return axis; - }; - var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { - top: 1, - right: 1, - bottom: 1, - left: 1 - }; - function d3_svg_axisX(selection, x) { - selection.attr("transform", function(d) { - return "translate(" + x(d) + ",0)"; - }); - } - function d3_svg_axisY(selection, y) { - selection.attr("transform", function(d) { - return "translate(0," + y(d) + ")"; - }); - } - function d3_svg_axisSubdivide(scale, ticks, m) { - subticks = []; - if (m && ticks.length > 1) { - var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v; - while (++i < n) { - for (j = m; --j > 0; ) { - if ((v = +ticks[i] - j * d) >= extent[0]) { - subticks.push(v); - } - } - } - for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) { - subticks.push(v); - } - } - return subticks; - } - d3.svg.brush = function() { - var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain; - function brush(g) { - g.each(function() { - var g = d3.select(this), bg = g.selectAll(".background").data([ 0 ]), fg = g.selectAll(".extent").data([ 0 ]), tz = g.selectAll(".resize").data(resizes, String), e; - g.style("pointer-events", "all").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); - bg.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); - fg.enter().append("rect").attr("class", "extent").style("cursor", "move"); - tz.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"); - tz.style("display", brush.empty() ? "none" : null); - tz.exit().remove(); - if (x) { - e = d3_scaleRange(x); - bg.attr("x", e[0]).attr("width", e[1] - e[0]); - redrawX(g); - } - if (y) { - e = d3_scaleRange(y); - bg.attr("y", e[0]).attr("height", e[1] - e[0]); - redrawY(g); - } - redraw(g); - }); - } - function redraw(g) { - g.selectAll(".resize").attr("transform", function(d) { - return "translate(" + extent[+/e$/.test(d)][0] + "," + extent[+/^s/.test(d)][1] + ")"; - }); - } - function redrawX(g) { - g.select(".extent").attr("x", extent[0][0]); - g.selectAll(".extent,.n>rect,.s>rect").attr("width", extent[1][0] - extent[0][0]); - } - function redrawY(g) { - g.select(".extent").attr("y", extent[0][1]); - g.selectAll(".extent,.e>rect,.w>rect").attr("height", extent[1][1] - extent[0][1]); - } - 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"), center, origin = mouse(), offset; - var w = d3.select(d3_window).on("mousemove.brush", brushmove).on("mouseup.brush", brushend).on("touchmove.brush", brushmove).on("touchend.brush", brushend).on("keydown.brush", keydown).on("keyup.brush", keyup); - if (dragging) { - origin[0] = extent[0][0] - origin[0]; - origin[1] = extent[0][1] - origin[1]; - } else if (resizing) { - var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); - offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ]; - origin[0] = extent[ex][0]; - origin[1] = extent[ey][1]; - } 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(); - d3_eventCancel(); - function mouse() { - var touches = d3.event.changedTouches; - return touches ? d3.touches(target, touches)[0] : d3.mouse(target); - } - function keydown() { - if (d3.event.keyCode == 32) { - if (!dragging) { - center = null; - origin[0] -= extent[1][0]; - origin[1] -= extent[1][1]; - dragging = 2; - } - d3_eventCancel(); - } - } - function keyup() { - if (d3.event.keyCode == 32 && dragging == 2) { - origin[0] += extent[1][0]; - origin[1] += extent[1][1]; - dragging = 0; - d3_eventCancel(); - } - } - function brushmove() { - var point = mouse(), moved = false; - if (offset) { - point[0] += offset[0]; - point[1] += offset[1]; - } - if (!dragging) { - if (d3.event.altKey) { - if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ]; - origin[0] = extent[+(point[0] < center[0])][0]; - origin[1] = extent[+(point[1] < center[1])][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" - }); - } - } - function move1(point, scale, i) { - var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max; - if (dragging) { - r0 -= position; - r1 -= size + position; - } - min = Math.max(r0, Math.min(r1, 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][i] !== min || extent[1][i] !== max) { - extentDomain = null; - extent[0][i] = min; - extent[1][i] = max; - return true; - } - } - 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); - event_({ - type: "brushend" - }); - d3_eventCancel(); - } - } - 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.extent = function(z) { - var x0, x1, y0, y1, t; - if (!arguments.length) { - z = extentDomain || extent; - if (x) { - x0 = z[0][0], x1 = z[1][0]; - if (!extentDomain) { - x0 = extent[0][0], x1 = extent[1][0]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - } - if (y) { - y0 = z[0][1], y1 = z[1][1]; - if (!extentDomain) { - y0 = extent[0][1], y1 = extent[1][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 ]; - } - extentDomain = [ [ 0, 0 ], [ 0, 0 ] ]; - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - extentDomain[0][0] = x0, extentDomain[1][0] = x1; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - extent[0][0] = x0 | 0, extent[1][0] = x1 | 0; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - extentDomain[0][1] = y0, extentDomain[1][1] = y1; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - extent[0][1] = y0 | 0, extent[1][1] = y1 | 0; - } - return brush; - }; - brush.clear = function() { - extentDomain = null; - extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0; - return brush; - }; - brush.empty = function() { - return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][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" ], [] ]; - d3.behavior = {}; - d3.behavior.drag = function() { - var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null; - function drag() { - this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown); - } - function mousedown() { - var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0; - var w = d3.select(d3_window).on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true); - if (origin) { - offset = origin.apply(target, arguments); - offset = [ offset.x - origin_[0], offset.y - origin_[1] ]; - } else { - offset = [ 0, 0 ]; - } - if (touchId == null) d3_eventCancel(); - event_({ - type: "dragstart" - }); - function point() { - var p = target.parentNode; - return touchId != null ? d3.touches(p).filter(function(p) { - return p.identifier === touchId; - })[0] : d3.mouse(p); - } - function dragmove() { - if (!target.parentNode) return dragend(); - var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1]; - moved |= dx | dy; - origin_ = p; - d3_eventCancel(); - event_({ - type: "drag", - x: p[0] + offset[0], - y: p[1] + offset[1], - dx: dx, - dy: dy - }); - } - function dragend() { - event_({ - type: "dragend" - }); - if (moved) { - d3_eventCancel(); - if (d3.event.target === eventTarget) w.on("click.drag", click, true); - } - w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null); - } - function click() { - d3_eventCancel(); - w.on("click.drag", null); - } - } - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - return d3.rebind(drag, event, "on"); - }; - d3.behavior.zoom = function() { - var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime; - function zoom() { - this.on("mousedown.zoom", mousedown).on("mousemove.zoom", mousemove).on(d3_behavior_zoomWheel + ".zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart); - } - zoom.translate = function(x) { - if (!arguments.length) return translate; - translate = x.map(Number); - rescale(); - return zoom; - }; - zoom.scale = function(x) { - if (!arguments.length) return scale; - scale = +x; - rescale(); - return zoom; - }; - zoom.scaleExtent = function(x) { - if (!arguments.length) return scaleExtent; - scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number); - return zoom; - }; - zoom.x = function(z) { - if (!arguments.length) return x1; - x1 = z; - x0 = z.copy(); - translate = [ 0, 0 ]; - scale = 1; - return zoom; - }; - zoom.y = function(z) { - if (!arguments.length) return y1; - y1 = z; - y0 = z.copy(); - translate = [ 0, 0 ]; - scale = 1; - return zoom; - }; - function location(p) { - return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ]; - } - function point(l) { - return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ]; - } - function scaleTo(s) { - scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); - } - function translateTo(p, l) { - l = point(l); - translate[0] += p[0] - l[0]; - translate[1] += p[1] - l[1]; - } - function rescale() { - if (x1) x1.domain(x0.range().map(function(x) { - return (x - translate[0]) / scale; - }).map(x0.invert)); - if (y1) y1.domain(y0.range().map(function(y) { - return (y - translate[1]) / scale; - }).map(y0.invert)); - } - function dispatch(event) { - rescale(); - d3.event.preventDefault(); - event({ - type: "zoom", - scale: scale, - translate: translate - }); - } - function mousedown() { - var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(d3_window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target)); - d3_window.focus(); - d3_eventCancel(); - function mousemove() { - moved = 1; - translateTo(d3.mouse(target), l); - dispatch(event_); - } - function mouseup() { - if (moved) d3_eventCancel(); - w.on("mousemove.zoom", null).on("mouseup.zoom", null); - if (moved && d3.event.target === eventTarget) w.on("click.zoom", click, true); - } - function click() { - d3_eventCancel(); - w.on("click.zoom", null); - } - } - function mousewheel() { - if (!translate0) translate0 = location(d3.mouse(this)); - scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale); - translateTo(d3.mouse(this), translate0); - dispatch(event.of(this, arguments)); - } - function mousemove() { - translate0 = null; - } - function dblclick() { - var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2; - scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1)); - translateTo(p, l); - dispatch(event.of(this, arguments)); - } - function touchstart() { - var touches = d3.touches(this), now = Date.now(); - scale0 = scale; - translate0 = {}; - touches.forEach(function(t) { - translate0[t.identifier] = location(t); - }); - d3_eventCancel(); - if (touches.length === 1) { - if (now - touchtime < 500) { - var p = touches[0], l = location(touches[0]); - scaleTo(scale * 2); - translateTo(p, l); - dispatch(event.of(this, arguments)); - } - touchtime = now; - } - } - function touchmove() { - var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier]; - if (p1 = touches[1]) { - var p1, l1 = translate0[p1.identifier]; - p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; - l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; - scaleTo(d3.event.scale * scale0); - } - translateTo(p0, l0); - touchtime = null; - dispatch(event.of(this, arguments)); - } - return d3.rebind(zoom, event, "on"); - }; - var d3_behavior_zoomInfinity = [ 0, Infinity ]; - var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in document ? (d3_behavior_zoomDelta = function() { - return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); - }, "wheel") : "onmousewheel" in document ? (d3_behavior_zoomDelta = function() { - return d3.event.wheelDelta; - }, "mousewheel") : (d3_behavior_zoomDelta = function() { - return -d3.event.detail; - }, "MozMousePixelScroll"); - 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 = (2 * π - 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 - }); - } - } - } - 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; - }; - 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; - }; - chord.sortChords = function(x) { - if (!arguments.length) return sortChords; - sortChords = x; - if (chords) resort(); - return chord; - }; - chord.chords = function() { - if (!chords) relayout(); - return chords; - }; - chord.groups = function() { - if (!groups) relayout(); - return groups; - }; - return chord; - }; - 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, gravity = .1, theta = .8, 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, dn = 1 / Math.sqrt(dx * dx + dy * dy); - if ((x2 - x1) * dn < theta) { - var k = quad.charge * dn * dn; - node.px -= dx * k; - node.py -= dy * k; - return true; - } - if (quad.point && isFinite(dn)) { - var k = quad.pointCharge * dn * dn; - node.px -= dx * k; - node.py -= dy * k; - } - } - return !quad.charge; - }; - } - 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 - }); - }; - 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; - }; - force.size = function(x) { - if (!arguments.length) return size; - size = x; - return force; - }; - force.linkDistance = function(x) { - if (!arguments.length) return linkDistance; - linkDistance = typeof x === "function" ? x : +x; - return force; - }; - force.distance = force.linkDistance; - force.linkStrength = function(x) { - if (!arguments.length) return linkStrength; - linkStrength = typeof x === "function" ? x : +x; - return force; - }; - force.friction = function(x) { - if (!arguments.length) return friction; - friction = +x; - return force; - }; - force.charge = function(x) { - if (!arguments.length) return charge; - charge = typeof x === "function" ? x : +x; - return force; - }; - force.gravity = function(x) { - if (!arguments.length) return gravity; - gravity = +x; - return force; - }; - force.theta = function(x) { - if (!arguments.length) return theta; - theta = +x; - return force; - }; - 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; - }; - force.start = function() { - var i, j, 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) { - var neighbors = neighbor(i), j = -1, m = neighbors.length, x; - while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x; - return Math.random() * size; - } - function neighbor() { - if (!neighbors) { - neighbors = []; - 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); - } - } - return neighbors[i]; - } - return force.resume(); - }; - force.resume = function() { - return force.alpha(.1); - }; - force.stop = function() { - return force.alpha(0); - }; - 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); - }; - 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.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 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; - } - 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 d3_layout_hierarchyRebind(partition, hierarchy); - }; - d3.layout.pie = function() { - var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * π; - function pie(data) { - var values = data.map(function(d, i) { - return +value.call(pie, d, i); - }); - var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle); - var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - startAngle) / d3.sum(values); - var index = d3.range(data.length); - 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]); - }); - var arcs = []; - index.forEach(function(i) { - var d; - arcs[i] = { - data: data[i], - value: d = values[i], - startAngle: a, - endAngle: a += d * k - }; - }); - return arcs; - } - pie.value = function(x) { - if (!arguments.length) return value; - value = x; - return pie; - }; - pie.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return pie; - }; - pie.startAngle = function(x) { - if (!arguments.length) return startAngle; - startAngle = x; - return pie; - }; - pie.endAngle = function(x) { - if (!arguments.length) return endAngle; - endAngle = x; - return pie; - }; - return pie; - }; - 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) { - 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 n = series.length, m = series[0].length, 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; - } - 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_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); - } - } - 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); - } - 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; - } - s2 += s3 * data[i][j][1]; - } - 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]); - } - } - } - 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_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_layout_histogramRange(values) { - return [ d3.min(values), d3.max(values) ]; - } - d3.layout.hierarchy = function() { - var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; - function recurse(node, depth, nodes) { - var childs = children.call(hierarchy, node, depth); - node.depth = depth; - nodes.push(node); - if (childs && (n = childs.length)) { - var i = -1, n, c = node.children = [], v = 0, j = depth + 1, d; - while (++i < n) { - d = recurse(childs[i], j, nodes); - d.parent = node; - c.push(d); - v += d.value; - } - if (sort) c.sort(sort); - if (value) node.value = v; - } else if (value) { - node.value = +value.call(hierarchy, node, depth) || 0; - } - return node; - } - function revalue(node, depth) { - var children = node.children, v = 0; - if (children && (n = children.length)) { - var i = -1, n, j = depth + 1; - while (++i < n) v += revalue(children[i], j); - } else if (value) { - v = +value.call(hierarchy, node, depth) || 0; - } - if (value) node.value = v; - return v; - } - function hierarchy(d) { - var nodes = []; - recurse(d, 0, nodes); - return nodes; - } - hierarchy.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return hierarchy; - }; - hierarchy.children = function(x) { - if (!arguments.length) return children; - children = x; - return hierarchy; - }; - hierarchy.value = function(x) { - if (!arguments.length) return value; - value = x; - return hierarchy; - }; - hierarchy.revalue = function(root) { - revalue(root, 0); - return root; - }; - return hierarchy; - }; - 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_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.pack = function() { - var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ]; - function pack(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0]; - root.x = 0; - root.y = 0; - d3_layout_treeVisitAfter(root, function(d) { - d.r = Math.sqrt(d.value); - }); - d3_layout_treeVisitAfter(root, d3_layout_packSiblings); - var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h); - if (padding > 0) { - var dr = padding * k / 2; - d3_layout_treeVisitAfter(root, function(d) { - d.r += dr; - }); - d3_layout_treeVisitAfter(root, d3_layout_packSiblings); - d3_layout_treeVisitAfter(root, function(d) { - d.r -= dr; - }); - k = Math.max(2 * root.r / w, 2 * root.r / h); - } - d3_layout_packTransform(root, w / 2, h / 2, 1 / k); - return nodes; - } - pack.size = function(x) { - if (!arguments.length) return size; - size = x; - 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_layout_packIntersects(a, b) { - var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; - return dr * dr - dx * dx - dy * dy > .001; - } - 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; - } - } - } - 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); - } - } - } - } - 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.cluster = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ]; - function cluster(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; - d3_layout_treeVisitAfter(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; - } - }); - 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_treeVisitAfter(root, 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; - } - cluster.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return cluster; - }; - cluster.size = function(x) { - if (!arguments.length) return size; - size = x; - 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_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; - } - d3.layout.tree = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ]; - function tree(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0]; - function firstWalk(node, previousSibling) { - var children = node.children, layout = node._tree; - if (children && (n = children.length)) { - var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1; - while (++i < n) { - child = children[i]; - firstWalk(child, previousChild); - ancestor = apportion(child, previousChild, ancestor); - previousChild = child; - } - d3_layout_treeShift(node); - var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim); - if (previousSibling) { - layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling); - layout.mod = layout.prelim - midpoint; - } else { - layout.prelim = midpoint; - } - } else { - if (previousSibling) { - layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling); - } - } - } - function secondWalk(node, x) { - node.x = node._tree.prelim + x; - var children = node.children; - if (children && (n = children.length)) { - var i = -1, n; - x += node._tree.mod; - while (++i < n) { - secondWalk(children[i], x); - } - } - } - function apportion(node, previousSibling, ancestor) { - if (previousSibling) { - var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, 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._tree.ancestor = node; - shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip); - if (shift > 0) { - d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift); - sip += shift; - sop += shift; - } - sim += vim._tree.mod; - sip += vip._tree.mod; - som += vom._tree.mod; - sop += vop._tree.mod; - } - if (vim && !d3_layout_treeRight(vop)) { - vop._tree.thread = vim; - vop._tree.mod += sim - sop; - } - if (vip && !d3_layout_treeLeft(vom)) { - vom._tree.thread = vip; - vom._tree.mod += sip - som; - ancestor = node; - } - } - return ancestor; - } - d3_layout_treeVisitAfter(root, function(node, previousSibling) { - node._tree = { - ancestor: node, - prelim: 0, - mod: 0, - change: 0, - shift: 0, - number: previousSibling ? previousSibling._tree.number + 1 : 0 - }; - }); - firstWalk(root); - secondWalk(root, -root._tree.prelim); - var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1; - d3_layout_treeVisitAfter(root, function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = node.depth / y1 * size[1]; - delete node._tree; - }); - return nodes; - } - tree.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return tree; - }; - tree.size = function(x) { - if (!arguments.length) return size; - size = x; - 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(node) { - var children = node.children; - return children && children.length ? children[0] : node._tree.thread; - } - function d3_layout_treeRight(node) { - var children = node.children, n; - return children && (n = children.length) ? children[n - 1] : node._tree.thread; - } - function d3_layout_treeSearch(node, compare) { - var children = node.children; - if (children && (n = children.length)) { - var child, n, i = -1; - while (++i < n) { - if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) { - node = child; - } - } - } - return node; - } - function d3_layout_treeRightmost(a, b) { - return a.x - b.x; - } - function d3_layout_treeLeftmost(a, b) { - return b.x - a.x; - } - function d3_layout_treeDeepest(a, b) { - return a.depth - b.depth; - } - function d3_layout_treeVisitAfter(node, callback) { - function visit(node, previousSibling) { - var children = node.children; - if (children && (n = children.length)) { - var child, previousChild = null, i = -1, n; - while (++i < n) { - child = children[i]; - visit(child, previousChild); - previousChild = child; - } - } - callback(node, previousSibling); - } - visit(node, null); - } - function d3_layout_treeShift(node) { - var shift = 0, change = 0, children = node.children, i = children.length, child; - while (--i >= 0) { - child = children[i]._tree; - child.prelim += shift; - child.mod += shift; - shift += child.shift + (change += child.change); - } - } - function d3_layout_treeMove(ancestor, node, shift) { - ancestor = ancestor._tree; - node = node._tree; - var change = shift / (node.number - ancestor.number); - ancestor.change += change; - node.change -= change; - node.shift += shift; - node.prelim += shift; - node.mod += shift; - } - function d3_layout_treeAncestor(vim, node, ancestor) { - return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor; - } - 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 (!(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; - } - } - 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; - } - treemap.size = function(x) { - if (!arguments.length) return size; - size = x; - return treemap; - }; - 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; - }; - treemap.round = function(x) { - if (!arguments.length) return round != Number; - round = x ? Math.round : Number; - return treemap; - }; - treemap.sticky = function(x) { - if (!arguments.length) return sticky; - sticky = x; - stickies = null; - return treemap; - }; - treemap.ratio = function(x) { - if (!arguments.length) return ratio; - ratio = x; - return treemap; - }; - treemap.mode = function(x) { - if (!arguments.length) return mode; - mode = x + ""; - return treemap; - }; - return d3_layout_hierarchyRebind(treemap, hierarchy); - }; - function d3_layout_treemapPadNull(node) { - return { - x: node.x, - y: node.y, - dx: node.dx, - dy: node.dy - }; - } - 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; - } - if (dy < 0) { - y += dy / 2; - dy = 0; - } - return { - x: x, - y: y, - dx: dx, - dy: dy - }; - } - function d3_dsv(delimiter, mimeType) { - var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); - function dsv(url, callback) { - return d3.xhr(url, mimeType, callback).response(response); - } - function response(request) { - return dsv.parse(request.responseText); - } - dsv.parse = function(text) { - var o; - return dsv.parseRows(text, function(row) { - if (o) return o(row); - o = new Function("d", "return {" + row.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); - }); - }; - 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.substring(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.substring(j, I - k); - } - return text.substring(j); - } - while ((t = token()) !== EOF) { - var a = []; - while (t !== EOL && t !== EOF) { - a.push(t); - t = token(); - } - if (f && !(a = f(a, n++))) continue; - rows.push(a); - } - return rows; - }; - dsv.format = function(rows) { - return rows.map(formatRow).join("\n"); - }; - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - function formatValue(text) { - return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; - } - return dsv; - } - d3.csv = d3_dsv(",", "text/csv"); - d3.tsv = d3_dsv(" ", "text/tab-separated-values"); - d3.geo = {}; - d3.geo.stream = function(object, listener) { - if (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 (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); - } - }; - var d3_geo_streamGeometryType = { - Sphere: function(object, listener) { - listener.sphere(); - }, - Point: function(object, listener) { - var coordinate = object.coordinates; - listener.point(coordinate[0], coordinate[1]); - }, - MultiPoint: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate; - while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]); - }, - 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_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]); - 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_geo_spherical(cartesian) { - return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ]; - } - function d3_geo_sphericalEqual(a, b) { - return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; - } - function d3_geo_cartesian(spherical) { - var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); - return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; - } - function d3_geo_cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[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] ]; - } - function d3_geo_cartesianAdd(a, b) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; - } - function d3_geo_cartesianScale(vector, k) { - return [ vector[0] * k, vector[1] * k, vector[2] * k ]; - } - 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_geo_resample(project) { - var δ2 = .5, maxDepth = 16; - function resample(stream) { - var λ0, x0, y0, a0, b0, c0; - var resample = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - stream.polygonStart(); - resample.lineStart = polygonLineStart; - }, - 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 polygonLineStart() { - var λ00, φ00, x00, y00, a00, b00, c00; - lineStart(); - resample.point = function(λ, φ) { - linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resample.point = linePoint; - }; - resample.lineEnd = function() { - 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 = Math.abs(Math.abs(c) - 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 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) { - 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.geo.albersUsa = function() { - var lower48 = d3.geo.albers(); - var alaska = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 60 ]).parallels([ 55, 65 ]); - var hawaii = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 20 ]).parallels([ 8, 18 ]); - var puertoRico = d3.geo.albers().rotate([ 60, 0 ]).center([ 0, 10 ]).parallels([ 8, 18 ]); - function albersUsa(coordinates) { - return projection(coordinates)(coordinates); - } - function projection(point) { - var lon = point[0], lat = point[1]; - return lat > 50 ? alaska : lon < -140 ? hawaii : lat < 21 ? puertoRico : lower48; - } - albersUsa.scale = function(x) { - if (!arguments.length) return lower48.scale(); - lower48.scale(x); - alaska.scale(x * .6); - hawaii.scale(x); - puertoRico.scale(x * 1.5); - return albersUsa.translate(lower48.translate()); - }; - albersUsa.translate = function(x) { - if (!arguments.length) return lower48.translate(); - var dz = lower48.scale(), dx = x[0], dy = x[1]; - lower48.translate(x); - alaska.translate([ dx - .4 * dz, dy + .17 * dz ]); - hawaii.translate([ dx - .19 * dz, dy + .2 * dz ]); - puertoRico.translate([ dx + .58 * dz, dy + .43 * dz ]); - return albersUsa; - }; - return albersUsa.scale(lower48.scale()); - }; - function d3_geo_albers(φ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 albers(λ, φ) { - var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; - return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; - } - albers.invert = function(x, y) { - var ρ0_y = ρ0 - y; - return [ Math.atan2(x, ρ0_y) / n, Math.asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; - }; - return albers; - } - (d3.geo.albers = function() { - var φ0 = 29.5 * d3_radians, φ1 = 45.5 * d3_radians, m = d3_geo_projectionMutator(d3_geo_albers), p = m(φ0, φ1); - p.parallels = function(_) { - if (!arguments.length) return [ φ0 * d3_degrees, φ1 * d3_degrees ]; - return m(φ0 = _[0] * d3_radians, φ1 = _[1] * d3_radians); - }; - return p.rotate([ 98, 0 ]).center([ 0, 38 ]).scale(1e3); - }).raw = d3_geo_albers; - 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; - d3.geo.bounds = d3_geo_bounds(d3_identity); - function d3_geo_bounds(projectStream) { - var x0, y0, x1, y1; - var bound = { - point: boundPoint, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - bound.lineEnd = boundPolygonLineEnd; - }, - polygonEnd: function() { - bound.point = boundPoint; - } - }; - function boundPoint(x, y) { - if (x < x0) x0 = x; - if (x > x1) x1 = x; - if (y < y0) y0 = y; - if (y > y1) y1 = y; - } - function boundPolygonLineEnd() { - bound.point = bound.lineEnd = d3_noop; - } - return function(feature) { - y1 = x1 = -(x0 = y0 = Infinity); - d3.geo.stream(feature, projectStream(bound)); - return [ [ x0, y0 ], [ x1, y1 ] ]; - }; - } - d3.geo.centroid = function(object) { - d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; - d3.geo.stream(object, d3_geo_centroid); - var m; - if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) { - return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ]; - } - }; - var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ; - var d3_geo_centroid = { - sphere: function() { - if (d3_geo_centroidDimension < 2) { - d3_geo_centroidDimension = 2; - d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; - } - }, - point: d3_geo_centroidPoint, - lineStart: d3_geo_centroidLineStart, - lineEnd: d3_geo_centroidLineEnd, - polygonStart: function() { - if (d3_geo_centroidDimension < 2) { - d3_geo_centroidDimension = 2; - d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; - } - d3_geo_centroid.lineStart = d3_geo_centroidRingStart; - }, - polygonEnd: function() { - d3_geo_centroid.lineStart = d3_geo_centroidLineStart; - } - }; - function d3_geo_centroidPoint(λ, φ) { - if (d3_geo_centroidDimension) return; - ++d3_geo_centroidW; - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - d3_geo_centroidX += (cosφ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW; - d3_geo_centroidY += (cosφ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW; - d3_geo_centroidZ += (Math.sin(φ) - d3_geo_centroidZ) / d3_geo_centroidW; - } - function d3_geo_centroidRingStart() { - var λ00, φ00; - d3_geo_centroidDimension = 1; - d3_geo_centroidLineStart(); - d3_geo_centroidDimension = 2; - var linePoint = d3_geo_centroid.point; - d3_geo_centroid.point = function(λ, φ) { - linePoint(λ00 = λ, φ00 = φ); - }; - d3_geo_centroid.lineEnd = function() { - d3_geo_centroid.point(λ00, φ00); - d3_geo_centroidLineEnd(); - d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; - }; - } - function d3_geo_centroidLineStart() { - var x0, y0, z0; - if (d3_geo_centroidDimension > 1) return; - if (d3_geo_centroidDimension < 1) { - d3_geo_centroidDimension = 1; - d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; - } - 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; - }; - 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_centroidW += w; - d3_geo_centroidX += w * (x0 + (x0 = x)); - d3_geo_centroidY += w * (y0 + (y0 = y)); - d3_geo_centroidZ += w * (z0 + (z0 = z)); - } - } - function d3_geo_centroidLineEnd() { - d3_geo_centroid.point = d3_geo_centroidPoint; - } - 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(radians, precision) { - var cr = Math.cos(radians), sr = Math.sin(radians); - return function(from, to, direction, listener) { - if (from != null) { - from = d3_geo_circleAngle(cr, from); - to = d3_geo_circleAngle(cr, to); - if (direction > 0 ? from < to : from > to) from += direction * 2 * π; - } else { - from = radians + direction * 2 * π; - to = radians; - } - var point; - for (var step = direction * precision, 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_geo_circleAngle(cr, point) { - var a = d3_geo_cartesian(point); - a[0] -= cr; - d3_geo_cartesianNormalize(a); - var angle = Math.acos(Math.max(-1, Math.min(1, -a[1]))); - return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); - } - function d3_geo_clip(pointVisible, clipLine, interpolate) { - return function(listener) { - var line = clipLine(listener); - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - invisible = false; - invisibleArea = visibleArea = 0; - segments = []; - listener.polygonStart(); - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = d3.merge(segments); - if (segments.length) { - d3_geo_clipPolygon(segments, interpolate, listener); - } else if (visibleArea < -ε || invisible && invisibleArea < -ε) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - listener.polygonEnd(); - segments = null; - }, - sphere: function() { - listener.polygonStart(); - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - listener.polygonEnd(); - } - }; - function point(λ, φ) { - if (pointVisible(λ, φ)) listener.point(λ, φ); - } - function pointLine(λ, φ) { - line.point(λ, φ); - } - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } - function lineEnd() { - clip.point = point; - line.lineEnd(); - } - var segments, visibleArea, invisibleArea, invisible; - var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring; - function pointRing(λ, φ) { - ringListener.point(λ, φ); - ring.push([ λ, φ ]); - } - 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; - if (!n) { - invisible = true; - invisibleArea += d3_geo_clipAreaRing(ring, -1); - ring = null; - return; - } - ring = null; - if (clean & 1) { - segment = ringSegments[0]; - visibleArea += d3_geo_clipAreaRing(segment, 1); - var n = segment.length - 1, i = -1, point; - 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_geo_clipPolygon(segments, interpolate, listener) { - var subject = [], clip = []; - segments.forEach(function(segment) { - if ((n = segment.length) <= 1) return; - var n, p0 = segment[0], p1 = segment[n - 1]; - 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 = { - point: p0, - points: segment, - other: null, - visited: false, - entry: true, - subject: true - }, b = { - point: p0, - points: [ p0 ], - other: a, - visited: false, - entry: false, - subject: false - }; - a.other = b; - subject.push(a); - clip.push(b); - a = { - point: p1, - points: [ p1 ], - other: null, - visited: false, - entry: false, - subject: true - }; - b = { - point: p1, - points: [ p1 ], - other: a, - visited: false, - entry: true, - subject: false - }; - a.other = b; - subject.push(a); - clip.push(b); - }); - clip.sort(d3_geo_clipSort); - d3_geo_clipLinkCircular(subject); - d3_geo_clipLinkCircular(clip); - if (!subject.length) return; - var start = subject[0], current, points, point; - while (1) { - current = start; - while (current.visited) if ((current = current.next) === start) return; - points = current.points; - listener.lineStart(); - do { - current.visited = current.other.visited = true; - if (current.entry) { - if (current.subject) { - for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.point, current.next.point, 1, listener); - } - current = current.next; - } else { - if (current.subject) { - points = current.prev.points; - for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.point, current.prev.point, -1, listener); - } - current = current.prev; - } - current = current.other; - points = current.points; - } while (!current.visited); - listener.lineEnd(); - } - } - function d3_geo_clipLinkCircular(array) { - if (!(n = array.length)) return; - var n, i = 0, a = array[0], b; - while (++i < n) { - a.next = b = array[i]; - b.prev = a; - a = b; - } - a.next = b = array[0]; - b.prev = a; - } - function d3_geo_clipSort(a, b) { - return ((a = a.point)[0] < 0 ? a[1] - π / 2 - ε : π / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - π / 2 - ε : π / 2 - b[1]); - } - function d3_geo_clipSegmentLength1(segment) { - return segment.length > 1; - } - 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; - } - }; - } - function d3_geo_clipAreaRing(ring, invisible) { - if (!(n = ring.length)) return 0; - var n, i = 0, area = 0, p = ring[0], λ = p[0], φ = p[1], cosφ = Math.cos(φ), x0 = Math.atan2(invisible * Math.sin(λ) * cosφ, Math.sin(φ)), y0 = 1 - invisible * Math.cos(λ) * cosφ, x1 = x0, x, y; - while (++i < n) { - p = ring[i]; - cosφ = Math.cos(φ = p[1]); - x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosφ, Math.sin(φ)); - y = 1 - invisible * Math.cos(λ) * cosφ; - if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue; - if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - π) < ε) { - if (y + y0 > 2) area += 4 * (x - x0); - } else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * π + x - x0) % (2 * π) - π) * (y0 + y); - x1 = x0, x0 = x, y0 = y; - } - return area; - } - var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate); - 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λ = Math.abs(λ1 - λ0); - if (Math.abs(dλ - π) < ε) { - listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? π / 2 : -π / 2); - 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 (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; - if (Math.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; - } - }; - } - function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { - var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); - return Math.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_geo_clipAntimeridianInterpolate(from, to, direction, listener) { - var φ; - if (from == null) { - φ = direction * π / 2; - listener.point(-π, φ); - listener.point(0, φ); - listener.point(π, φ); - listener.point(π, 0); - listener.point(π, -φ); - listener.point(0, -φ); - listener.point(-π, -φ); - listener.point(-π, 0); - listener.point(-π, φ); - } else if (Math.abs(from[0] - to[0]) > ε) { - var s = (from[0] < to[0] ? 1 : -1) * π; - φ = direction * s / 2; - listener.point(-s, φ); - listener.point(0, φ); - listener.point(s, φ); - } else { - listener.point(to[0], to[1]); - } - } - function d3_geo_clipCircle(degrees) { - var radians = degrees * d3_radians, cr = Math.cos(radians), interpolate = d3_geo_circleInterpolate(radians, 6 * d3_radians); - return d3_geo_clip(visible, clipLine, interpolate); - function visible(λ, φ) { - return Math.cos(λ) * Math.cos(φ) > cr; - } - function clipLine(listener) { - var point0, v0, v00, clean; - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(λ, φ) { - var point1 = [ λ, φ ], point2, v = visible(λ, φ); - 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 (v0 = 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; - } - if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) listener.point(point1[0], point1[1]); - point0 = point1; - }, - lineEnd: function() { - if (v0) listener.lineEnd(); - point0 = null; - }, - clean: function() { - return clean | (v00 && v0) << 1; - } - }; - } - function intersect(a, b) { - var pa = d3_geo_cartesian(a, 0), pb = d3_geo_cartesian(b, 0); - 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 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), t = Math.sqrt(w * w - uu * (d3_geo_cartesianDot(A, A) - 1)), q = d3_geo_cartesianScale(u, (-w - t) / uu); - d3_geo_cartesianAdd(q, A); - return d3_geo_spherical(q); - } - } - function d3_geo_compose(a, b) { - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } - 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_geo_equirectangular(λ, φ) { - return [ λ, φ ]; - } - (d3.geo.equirectangular = function() { - return d3_geo_projection(d3_geo_equirectangular).scale(250 / π); - }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; - 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; - d3.geo.graticule = function() { - var x1, x0, y1, y0, dx = 22.5, dy = dx, 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)); - } - 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 [ [ 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 [ dx, dy ]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = d3_geo_graticuleX(y0, y1, precision); - y = d3_geo_graticuleY(x0, x1, precision); - return graticule; - }; - return graticule.extent([ [ -180 + ε, -90 + ε ], [ 180 - ε, 90 - ε ] ]); - }; - 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_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_geo_haversin(x) { - return (x = Math.sin(x / 2)) * x; - } - 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_geo_haversin(y1 - y0) + cy0 * cy1 * d3_geo_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; - } - d3.geo.greatArc = function() { - var source = d3_source, source_, target = d3_target, target_, precision = 6 * d3_radians, interpolate; - function greatArc() { - var p0 = source_ || source.apply(this, arguments), p1 = target_ || target.apply(this, arguments), i = interpolate || d3.geo.interpolate(p0, p1), t = 0, dt = precision / i.distance, coordinates = [ p0 ]; - while ((t += dt) < 1) coordinates.push(i(t)); - coordinates.push(p1); - return { - type: "LineString", - coordinates: coordinates - }; - } - greatArc.distance = function() { - return (interpolate || d3.geo.interpolate(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments))).distance; - }; - greatArc.source = function(_) { - if (!arguments.length) return source; - source = _, source_ = typeof _ === "function" ? null : _; - interpolate = source_ && target_ ? d3.geo.interpolate(source_, target_) : null; - return greatArc; - }; - greatArc.target = function(_) { - if (!arguments.length) return target; - target = _, target_ = typeof _ === "function" ? null : _; - interpolate = source_ && target_ ? d3.geo.interpolate(source_, target_) : null; - return greatArc; - }; - greatArc.precision = function(_) { - if (!arguments.length) return precision / d3_radians; - precision = _ * d3_radians; - return greatArc; - }; - return greatArc; - }; - function d3_geo_mercator(λ, φ) { - return [ λ / (2 * π), Math.max(-.5, Math.min(+.5, Math.log(Math.tan(π / 4 + φ / 2)) / (2 * π))) ]; - } - d3_geo_mercator.invert = function(x, y) { - return [ 2 * π * x, 2 * Math.atan(Math.exp(2 * π * y)) - π / 2 ]; - }; - (d3.geo.mercator = function() { - return d3_geo_projection(d3_geo_mercator).scale(500); - }).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; - d3.geo.path = function() { - var pointRadius = 4.5, projection, context, projectStream, contextStream; - function path(object) { - if (object) d3.geo.stream(object, projectStream(contextStream.pointRadius(typeof pointRadius === "function" ? +pointRadius.apply(this, arguments) : pointRadius))); - 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_centroidDimension = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; - d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); - return d3_geo_centroidZ ? [ d3_geo_centroidX / d3_geo_centroidZ, d3_geo_centroidY / d3_geo_centroidZ ] : undefined; - }; - path.bounds = function(object) { - return d3_geo_bounds(projectStream)(object); - }; - path.projection = function(_) { - if (!arguments.length) return projection; - projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; - return path; - }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); - return path; - }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : +_; - return path; - }; - return path.projection(d3.geo.albersUsa()).context(null); - }; - function d3_geo_pathCircle(radius) { - return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + +2 * radius + "z"; - } - function d3_geo_pathProjectStream(project) { - var resample = d3_geo_resample(function(λ, φ) { - return project([ λ * d3_degrees, φ * d3_degrees ]); - }); - return function(stream) { - stream = resample(stream); - return { - point: function(λ, φ) { - stream.point(λ * d3_radians, φ * d3_radians); - }, - sphere: function() { - stream.sphere(); - }, - lineStart: function() { - stream.lineStart(); - }, - lineEnd: function() { - stream.lineEnd(); - }, - polygonStart: function() { - stream.polygonStart(); - }, - polygonEnd: function() { - stream.polygonEnd(); - } - }; - }; - } - function d3_geo_pathBuffer() { - var pointCircle = d3_geo_pathCircle(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_pathCircle(_); - return stream; - }, - result: function() { - if (buffer.length) { - var result = buffer.join(""); - buffer = []; - return result; - } - } - }; - 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_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, y); - context.arc(x, y, pointRadius, 0, 2 * π); - } - 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; - } - 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 += Math.abs(d3_geo_pathAreaPolygon / 2); - } - }; - 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); - }; - } - 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; - }, - 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) { - if (d3_geo_centroidDimension) return; - d3_geo_centroidX += x; - d3_geo_centroidY += y; - ++d3_geo_centroidZ; - } - function d3_geo_pathCentroidLineStart() { - var x0, y0; - if (d3_geo_centroidDimension !== 1) { - if (d3_geo_centroidDimension < 1) { - d3_geo_centroidDimension = 1; - d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; - } else return; - } - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - x0 = x, y0 = y; - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX += z * (x0 + x) / 2; - d3_geo_centroidY += z * (y0 + y) / 2; - d3_geo_centroidZ += z; - x0 = x, y0 = y; - } - } - function d3_geo_pathCentroidLineEnd() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - } - function d3_geo_pathCentroidRingStart() { - var x00, y00, x0, y0; - if (d3_geo_centroidDimension < 2) { - d3_geo_centroidDimension = 2; - d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; - } - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - x00 = x0 = x, y00 = y0 = y; - }; - function nextPoint(x, y) { - var z = y0 * x - x0 * y; - d3_geo_centroidX += z * (x0 + x); - d3_geo_centroidY += z * (y0 + y); - d3_geo_centroidZ += z * 3; - x0 = x, y0 = y; - } - d3_geo_pathCentroid.lineEnd = function() { - nextPoint(x00, y00); - }; - } - 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_areaRingU, d3_geo_areaRingV; - var d3_geo_area = { - sphere: function() { - d3_geo_areaSum += 4 * π; - }, - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_areaRingU = 1, d3_geo_areaRingV = 0; - d3_geo_area.lineStart = d3_geo_areaRingStart; - }, - polygonEnd: function() { - var area = 2 * Math.atan2(d3_geo_areaRingV, d3_geo_areaRingU); - 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_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, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u0 = d3_geo_areaRingU, v0 = d3_geo_areaRingV, u = cosφ0 * cosφ + k * Math.cos(dλ), v = k * Math.sin(dλ); - d3_geo_areaRingU = u0 * u - v0 * v; - d3_geo_areaRingV = v0 * u + u0 * v; - λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; - } - d3_geo_area.lineEnd = function() { - nextPoint(λ00, φ00); - }; - } - 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, clip = d3_geo_clipAntimeridian, clipAngle = null; - function projection(point) { - point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); - return [ point[0] * k + δx, δy - point[1] * k ]; - } - function invert(point) { - point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); - return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; - } - projection.stream = function(stream) { - return d3_geo_projectionRadiansRotate(rotate, clip(projectResample(stream))); - }; - projection.clipAngle = function(_) { - if (!arguments.length) return clipAngle; - clip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle(clipAngle = +_); - return projection; - }; - 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 projection; - } - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return reset(); - }; - } - function d3_geo_projectionRadiansRotate(rotate, stream) { - return { - point: function(x, y) { - y = rotate(x * d3_radians, y * d3_radians), x = y[0]; - stream.point(x > π ? x - 2 * π : x < -π ? x + 2 * π : x, y[1]); - }, - sphere: function() { - stream.sphere(); - }, - lineStart: function() { - stream.lineStart(); - }, - lineEnd: function() { - stream.lineEnd(); - }, - polygonStart: function() { - stream.polygonStart(); - }, - polygonEnd: function() { - stream.polygonEnd(); - } - }; - } - function d3_geo_rotation(δλ, δφ, δγ) { - return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_equirectangular; - } - function d3_geo_forwardRotationλ(δλ) { - return function(λ, φ) { - return λ += δλ, [ λ > π ? λ - 2 * π : λ < -π ? λ + 2 * π : λ, φ ]; - }; - } - 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δφ), Math.asin(Math.max(-1, Math.min(1, 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δφ), Math.asin(Math.max(-1, Math.min(1, k * cosδφ - x * sinδφ))) ]; - }; - return rotation; - } - 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_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; - } - d3.geom = {}; - d3.geom.hull = function(vertices) { - if (vertices.length < 3) return []; - var len = vertices.length, plen = len - 1, points = [], stack = [], i, j, h = 0, x1, y1, x2, y2, u, v, a, sp; - for (i = 1; i < len; ++i) { - if (vertices[i][1] < vertices[h][1]) { - h = i; - } else if (vertices[i][1] == vertices[h][1]) { - h = vertices[i][0] < vertices[h][0] ? i : h; - } - } - for (i = 0; i < len; ++i) { - if (i === h) continue; - y1 = vertices[i][1] - vertices[h][1]; - x1 = vertices[i][0] - vertices[h][0]; - points.push({ - angle: Math.atan2(y1, x1), - index: i - }); - } - points.sort(function(a, b) { - return a.angle - b.angle; - }); - a = points[0].angle; - v = points[0].index; - u = 0; - for (i = 1; i < plen; ++i) { - j = points[i].index; - if (a == points[i].angle) { - x1 = vertices[v][0] - vertices[h][0]; - y1 = vertices[v][1] - vertices[h][1]; - x2 = vertices[j][0] - vertices[h][0]; - y2 = vertices[j][1] - vertices[h][1]; - if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) { - points[i].index = -1; - } else { - points[u].index = -1; - a = points[i].angle; - u = i; - v = j; - } - } else { - a = points[i].angle; - u = i; - v = j; - } - } - stack.push(h); - for (i = 0, j = 0; i < 2; ++j) { - if (points[j].index !== -1) { - stack.push(points[j].index); - i++; - } - } - sp = stack.length; - for (;j < plen; ++j) { - if (points[j].index === -1) continue; - while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) { - --sp; - } - stack[sp++] = points[j].index; - } - var poly = []; - for (i = 0; i < sp; ++i) { - poly.push(vertices[stack[i]]); - } - return poly; - }; - function d3_geom_hullCCW(i1, i2, i3, v) { - var t, a, b, c, d, e, f; - t = v[i1]; - a = t[0]; - b = t[1]; - t = v[i2]; - c = t[0]; - d = t[1]; - t = v[i3]; - e = t[0]; - f = t[1]; - return (f - b) * (c - a) - (d - b) * (e - a) > 0; - } - d3.geom.polygon = function(coordinates) { - coordinates.area = function() { - var i = 0, n = coordinates.length, area = coordinates[n - 1][1] * coordinates[0][0] - coordinates[n - 1][0] * coordinates[0][1]; - while (++i < n) { - area += coordinates[i - 1][1] * coordinates[i][0] - coordinates[i - 1][0] * coordinates[i][1]; - } - return area * .5; - }; - coordinates.centroid = function(k) { - var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c; - if (!arguments.length) k = -1 / (6 * coordinates.area()); - while (++i < n) { - a = b; - b = coordinates[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 ]; - }; - coordinates.clip = function(subject) { - var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d; - while (++i < n) { - input = subject.slice(); - subject.length = 0; - b = coordinates[i]; - c = input[(m = input.length) - 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; - } - a = b; - } - return subject; - }; - return coordinates; - }; - 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 ]; - } - d3.geom.voronoi = function(vertices) { - var polygons = vertices.map(function() { - return []; - }), Z = 1e6; - d3_voronoi_tessellate(vertices, function(e) { - var s1, s2, x1, x2, y1, y2; - if (e.a === 1 && e.b >= 0) { - s1 = e.ep.r; - s2 = e.ep.l; - } else { - s1 = e.ep.l; - s2 = e.ep.r; - } - if (e.a === 1) { - y1 = s1 ? s1.y : -Z; - x1 = e.c - e.b * y1; - y2 = s2 ? s2.y : Z; - x2 = e.c - e.b * y2; - } else { - x1 = s1 ? s1.x : -Z; - y1 = e.c - e.a * x1; - x2 = s2 ? s2.x : Z; - y2 = e.c - e.a * x2; - } - var v1 = [ x1, y1 ], v2 = [ x2, y2 ]; - polygons[e.region.l.index].push(v1, v2); - polygons[e.region.r.index].push(v1, v2); - }); - polygons = polygons.map(function(polygon, i) { - var cx = vertices[i][0], cy = vertices[i][1], angle = polygon.map(function(v) { - return Math.atan2(v[0] - cx, v[1] - cy); - }), order = d3.range(polygon.length).sort(function(a, b) { - return angle[a] - angle[b]; - }); - return order.filter(function(d, i) { - return !i || angle[d] - angle[order[i - 1]] > ε; - }).map(function(d) { - return polygon[d]; - }); - }); - polygons.forEach(function(polygon, i) { - var n = polygon.length; - if (!n) return polygon.push([ -Z, -Z ], [ -Z, Z ], [ Z, Z ], [ Z, -Z ]); - if (n > 2) return; - var p0 = vertices[i], p1 = polygon[0], p2 = polygon[1], x0 = p0[0], y0 = p0[1], x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1], dx = Math.abs(x2 - x1), dy = y2 - y1; - if (Math.abs(dy) < ε) { - var y = y0 < y1 ? -Z : Z; - polygon.push([ -Z, y ], [ Z, y ]); - } else if (dx < ε) { - var x = x0 < x1 ? -Z : Z; - polygon.push([ x, -Z ], [ x, Z ]); - } else { - var y = (x2 - x1) * (y1 - y0) < (x1 - x0) * (y2 - y1) ? Z : -Z, z = Math.abs(dy) - dx; - if (Math.abs(z) < ε) { - polygon.push([ dy < 0 ? y : -y, y ]); - } else { - if (z > 0) y *= -1; - polygon.push([ -Z, y ], [ Z, y ]); - } - } - }); - return polygons; - }; - var d3_voronoi_opposite = { - l: "r", - r: "l" - }; - function d3_voronoi_tessellate(vertices, callback) { - var Sites = { - list: vertices.map(function(v, i) { - return { - index: i, - x: v[0], - y: v[1] - }; - }).sort(function(a, b) { - return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0; - }), - bottomSite: null - }; - var EdgeList = { - list: [], - leftEnd: null, - rightEnd: null, - init: function() { - EdgeList.leftEnd = EdgeList.createHalfEdge(null, "l"); - EdgeList.rightEnd = EdgeList.createHalfEdge(null, "l"); - EdgeList.leftEnd.r = EdgeList.rightEnd; - EdgeList.rightEnd.l = EdgeList.leftEnd; - EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd); - }, - createHalfEdge: function(edge, side) { - return { - edge: edge, - side: side, - vertex: null, - l: null, - r: null - }; - }, - insert: function(lb, he) { - he.l = lb; - he.r = lb.r; - lb.r.l = he; - lb.r = he; - }, - leftBound: function(p) { - var he = EdgeList.leftEnd; - do { - he = he.r; - } while (he != EdgeList.rightEnd && Geom.rightOf(he, p)); - he = he.l; - return he; - }, - del: function(he) { - he.l.r = he.r; - he.r.l = he.l; - he.edge = null; - }, - right: function(he) { - return he.r; - }, - left: function(he) { - return he.l; - }, - leftRegion: function(he) { - return he.edge == null ? Sites.bottomSite : he.edge.region[he.side]; - }, - rightRegion: function(he) { - return he.edge == null ? Sites.bottomSite : he.edge.region[d3_voronoi_opposite[he.side]]; - } - }; - var Geom = { - bisect: function(s1, s2) { - var newEdge = { - region: { - l: s1, - r: s2 - }, - ep: { - l: null, - r: null - } - }; - var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy; - newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5; - if (adx > ady) { - newEdge.a = 1; - newEdge.b = dy / dx; - newEdge.c /= dx; - } else { - newEdge.b = 1; - newEdge.a = dx / dy; - newEdge.c /= dy; - } - return newEdge; - }, - intersect: function(el1, el2) { - var e1 = el1.edge, e2 = el2.edge; - if (!e1 || !e2 || e1.region.r == e2.region.r) { - return null; - } - var d = e1.a * e2.b - e1.b * e2.a; - if (Math.abs(d) < 1e-10) { - return null; - } - var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e; - if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) { - el = el1; - e = e1; - } else { - el = el2; - e = e2; - } - var rightOfSite = xint >= e.region.r.x; - if (rightOfSite && el.side === "l" || !rightOfSite && el.side === "r") { - return null; - } - return { - x: xint, - y: yint - }; - }, - rightOf: function(he, p) { - var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x; - if (rightOfSite && he.side === "l") { - return 1; - } - if (!rightOfSite && he.side === "r") { - return 0; - } - if (e.a === 1) { - var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0; - if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) { - above = fast = dyp >= e.b * dxp; - } else { - above = p.x + p.y * e.b > e.c; - if (e.b < 0) { - above = !above; - } - if (!above) { - fast = 1; - } - } - if (!fast) { - var dxs = topsite.x - e.region.l.x; - above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b); - if (e.b < 0) { - above = !above; - } - } - } else { - var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y; - above = t1 * t1 > t2 * t2 + t3 * t3; - } - return he.side === "l" ? above : !above; - }, - endPoint: function(edge, side, site) { - edge.ep[side] = site; - if (!edge.ep[d3_voronoi_opposite[side]]) return; - callback(edge); - }, - distance: function(s, t) { - var dx = s.x - t.x, dy = s.y - t.y; - return Math.sqrt(dx * dx + dy * dy); - } - }; - var EventQueue = { - list: [], - insert: function(he, site, offset) { - he.vertex = site; - he.ystar = site.y + offset; - for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) { - var next = list[i]; - if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) { - continue; - } else { - break; - } - } - list.splice(i, 0, he); - }, - del: function(he) { - for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {} - ls.splice(i, 1); - }, - empty: function() { - return EventQueue.list.length === 0; - }, - nextEvent: function(he) { - for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) { - if (ls[i] == he) return ls[i + 1]; - } - return null; - }, - min: function() { - var elem = EventQueue.list[0]; - return { - x: elem.vertex.x, - y: elem.ystar - }; - }, - extractMin: function() { - return EventQueue.list.shift(); - } - }; - EdgeList.init(); - Sites.bottomSite = Sites.list.shift(); - var newSite = Sites.list.shift(), newIntStar; - var lbnd, rbnd, llbnd, rrbnd, bisector; - var bot, top, temp, p, v; - var e, pm; - while (true) { - if (!EventQueue.empty()) { - newIntStar = EventQueue.min(); - } - if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) { - lbnd = EdgeList.leftBound(newSite); - rbnd = EdgeList.right(lbnd); - bot = EdgeList.rightRegion(lbnd); - e = Geom.bisect(bot, newSite); - bisector = EdgeList.createHalfEdge(e, "l"); - EdgeList.insert(lbnd, bisector); - p = Geom.intersect(lbnd, bisector); - if (p) { - EventQueue.del(lbnd); - EventQueue.insert(lbnd, p, Geom.distance(p, newSite)); - } - lbnd = bisector; - bisector = EdgeList.createHalfEdge(e, "r"); - EdgeList.insert(lbnd, bisector); - p = Geom.intersect(bisector, rbnd); - if (p) { - EventQueue.insert(bisector, p, Geom.distance(p, newSite)); - } - newSite = Sites.list.shift(); - } else if (!EventQueue.empty()) { - lbnd = EventQueue.extractMin(); - llbnd = EdgeList.left(lbnd); - rbnd = EdgeList.right(lbnd); - rrbnd = EdgeList.right(rbnd); - bot = EdgeList.leftRegion(lbnd); - top = EdgeList.rightRegion(rbnd); - v = lbnd.vertex; - Geom.endPoint(lbnd.edge, lbnd.side, v); - Geom.endPoint(rbnd.edge, rbnd.side, v); - EdgeList.del(lbnd); - EventQueue.del(rbnd); - EdgeList.del(rbnd); - pm = "l"; - if (bot.y > top.y) { - temp = bot; - bot = top; - top = temp; - pm = "r"; - } - e = Geom.bisect(bot, top); - bisector = EdgeList.createHalfEdge(e, pm); - EdgeList.insert(llbnd, bisector); - Geom.endPoint(e, d3_voronoi_opposite[pm], v); - p = Geom.intersect(llbnd, bisector); - if (p) { - EventQueue.del(llbnd); - EventQueue.insert(llbnd, p, Geom.distance(p, bot)); - } - p = Geom.intersect(bisector, rrbnd); - if (p) { - EventQueue.insert(bisector, p, Geom.distance(p, bot)); - } - } else { - break; - } - } - for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) { - callback(lbnd.edge); - } - } - d3.geom.delaunay = function(vertices) { - var edges = vertices.map(function() { - return []; - }), triangles = []; - d3_voronoi_tessellate(vertices, function(e) { - edges[e.region.l.index].push(vertices[e.region.r.index]); - }); - edges.forEach(function(edge, i) { - var v = vertices[i], cx = v[0], cy = v[1]; - edge.forEach(function(v) { - v.angle = Math.atan2(v[0] - cx, v[1] - cy); - }); - edge.sort(function(a, b) { - return a.angle - b.angle; - }); - for (var j = 0, m = edge.length - 1; j < m; j++) { - triangles.push([ v, edge[j], edge[j + 1] ]); - } - }); - return triangles; - }; - d3.geom.quadtree = function(points, x1, y1, x2, y2) { - var p, i = -1, n = points.length; - if (arguments.length < 5) { - if (arguments.length === 3) { - y2 = y1; - x2 = x1; - y1 = x1 = 0; - } else { - x1 = y1 = Infinity; - x2 = y2 = -Infinity; - while (++i < n) { - p = points[i]; - if (p.x < x1) x1 = p.x; - if (p.y < y1) y1 = p.y; - if (p.x > x2) x2 = p.x; - if (p.y > y2) y2 = p.y; - } - } - } - var dx = x2 - x1, dy = y2 - y1; - if (dx > dy) y2 = y1 + dx; else x2 = x1 + dy; - function insert(n, p, x1, y1, x2, y2) { - if (isNaN(p.x) || isNaN(p.y)) return; - if (n.leaf) { - var v = n.point; - if (v) { - if (Math.abs(v.x - p.x) + Math.abs(v.y - p.y) < .01) { - insertChild(n, p, x1, y1, x2, y2); - } else { - n.point = null; - insertChild(n, v, x1, y1, x2, y2); - insertChild(n, p, x1, y1, x2, y2); - } - } else { - n.point = p; - } - } else { - insertChild(n, p, x1, y1, x2, y2); - } - } - function insertChild(n, p, x1, y1, x2, y2) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = p.x >= sx, bottom = p.y >= sy, i = (bottom << 1) + right; - n.leaf = false; - n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); - if (right) x1 = sx; else x2 = sx; - if (bottom) y1 = sy; else y2 = sy; - insert(n, p, x1, y1, x2, y2); - } - var root = d3_geom_quadtreeNode(); - root.add = function(p) { - insert(root, p, x1, y1, x2, y2); - }; - root.visit = function(f) { - d3_geom_quadtreeVisit(f, root, x1, y1, x2, y2); - }; - points.forEach(root.add); - return root; - }; - function d3_geom_quadtreeNode() { - return { - leaf: true, - nodes: [], - point: null - }; - } - 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); - } - } - d3.time = {}; - var d3_time = Date, d3_time_daySymbols = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; - function d3_time_utc() { - this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); - } - d3_time_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_time_prototype = Date.prototype; - var d3_time_formatDateTime = "%a %b %e %X %Y", d3_time_formatDate = "%m/%d/%Y", d3_time_formatTime = "%H:%M:%S"; - var d3_time_days = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], d3_time_dayAbbreviations = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], d3_time_months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], d3_time_monthAbbreviations = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; - d3.time.format = function(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.substring(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.substring(j, i)); - return string.join(""); - } - format.parse = function(string) { - var d = { - y: 1900, - m: 0, - d: 1, - H: 0, - M: 0, - S: 0, - L: 0 - }, 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 date = new d3_time(); - date.setFullYear(d.y, d.m, d.d); - date.setHours(d.H, d.M, d.S, d.L); - return date; - }; - format.toString = function() { - return template; - }; - return format; - }; - function d3_time_parse(date, template, string, j) { - var c, p, i = 0, n = template.length, m = string.length; - while (i < n) { - if (j >= m) return -1; - c = template.charCodeAt(i++); - if (c === 37) { - p = d3_time_parsers[template.charAt(i++)]; - if (!p || (j = p(date, string, j)) < 0) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - return j; - } - 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_formatPad(value, fill, width) { - value += ""; - var length = value.length; - return length < width ? new Array(width - length + 1).join(fill) + value : value; - } - var d3_time_dayRe = d3_time_formatRe(d3_time_days), d3_time_dayAbbrevRe = d3_time_formatRe(d3_time_dayAbbreviations), d3_time_monthRe = d3_time_formatRe(d3_time_months), d3_time_monthLookup = d3_time_formatLookup(d3_time_months), d3_time_monthAbbrevRe = d3_time_formatRe(d3_time_monthAbbreviations), d3_time_monthAbbrevLookup = d3_time_formatLookup(d3_time_monthAbbreviations); - var d3_time_formatPads = { - "-": "", - _: " ", - "0": "0" - }; - var d3_time_formats = { - a: function(d) { - return d3_time_dayAbbreviations[d.getDay()]; - }, - A: function(d) { - return d3_time_days[d.getDay()]; - }, - b: function(d) { - return d3_time_monthAbbreviations[d.getMonth()]; - }, - B: function(d) { - return d3_time_months[d.getMonth()]; - }, - c: d3.time.format(d3_time_formatDateTime), - 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 d.getHours() >= 12 ? "PM" : "AM"; - }, - 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(d3_time_formatDate), - X: d3.time.format(d3_time_formatTime), - 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 "%"; - } - }; - 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, - L: d3_time_parseMilliseconds, - m: d3_time_parseMonthNumber, - M: d3_time_parseMinutes, - p: d3_time_parseAmPm, - S: d3_time_parseSeconds, - x: d3_time_parseLocaleDate, - X: d3_time_parseLocaleTime, - y: d3_time_parseYear, - Y: d3_time_parseFullYear - }; - function d3_time_parseWeekdayAbbrev(date, string, i) { - d3_time_dayAbbrevRe.lastIndex = 0; - var n = d3_time_dayAbbrevRe.exec(string.substring(i)); - return n ? i += n[0].length : -1; - } - function d3_time_parseWeekday(date, string, i) { - d3_time_dayRe.lastIndex = 0; - var n = d3_time_dayRe.exec(string.substring(i)); - return n ? i += n[0].length : -1; - } - function d3_time_parseMonthAbbrev(date, string, i) { - d3_time_monthAbbrevRe.lastIndex = 0; - var n = d3_time_monthAbbrevRe.exec(string.substring(i)); - return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i += n[0].length) : -1; - } - function d3_time_parseMonth(date, string, i) { - d3_time_monthRe.lastIndex = 0; - var n = d3_time_monthRe.exec(string.substring(i)); - return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i += n[0].length) : -1; - } - 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_parseFullYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(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.substring(i, i + 2)); - return n ? (date.y = d3_time_expandYear(+n[0]), i += n[0].length) : -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.substring(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.substring(i, i + 2)); - return n ? (date.d = +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.substring(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.substring(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.substring(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.substring(i, i + 3)); - return n ? (date.L = +n[0], i += n[0].length) : -1; - } - var d3_time_numberRe = /^\s*\d+/; - function d3_time_parseAmPm(date, string, i) { - var n = d3_time_amPmLookup.get(string.substring(i, i += 2).toLowerCase()); - return n == null ? -1 : (date.p = n, i); - } - var d3_time_amPmLookup = d3.map({ - am: 0, - pm: 1 - }); - function d3_time_zone(d) { - var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = ~~(Math.abs(z) / 60), zm = Math.abs(z) % 60; - return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); - } - d3.time.format.utc = function(template) { - var local = d3.time.format(template); - function format(date) { - try { - d3_time = d3_time_utc; - var utc = new d3_time(); - utc._ = date; - return local(utc); - } finally { - d3_time = Date; - } - } - format.parse = function(string) { - try { - d3_time = d3_time_utc; - var date = local.parse(string); - return date && date._; - } finally { - d3_time = Date; - } - }; - format.toString = local.toString; - return format; - }; - var d3_time_formatIso = d3.time.format.utc("%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; - 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; - } - function ceil(date) { - step(date = local(new d3_time(date - 1)), 1); - return date; - } - function offset(date, k) { - step(date = new d3_time(+date), k); - return date; - } - 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); - } - } else { - while (time < t1) times.push(new Date(+time)), step(time, 1); - } - return times; - } - function range_utc(t0, t1, dt) { - try { - d3_time = d3_time_utc; - var utc = new d3_time_utc(); - utc._ = t0; - return range(utc, t1, dt); - } finally { - d3_time = Date; - } - } - 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 d3_time_interval_utc(method) { - return function(date, k) { - try { - d3_time = d3_time_utc; - var utc = new d3_time_utc(); - utc._ = date; - return method(utc, k)._; - } finally { - d3_time = Date; - } - }; - } - d3.time.second = d3_time_interval(function(date) { - return new d3_time(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_time(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_time((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.day = d3_time_interval(function(date) { - var day = new d3_time(1970, 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_time_daySymbols.forEach(function(day, i) { - day = day.toLowerCase(); - 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); - }); - 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; - 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; - 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; - function d3_time_scale(linear, methods, format) { - function scale(x) { - return linear(x); - } - 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; - }; - scale.nice = function(m) { - return scale.domain(d3_scale_nice(scale.domain(), function() { - return m; - })); - }; - scale.ticks = function(m, k) { - var extent = d3_time_scaleExtent(scale.domain()); - if (typeof m !== "function") { - var span = extent[1] - extent[0], target = span / m, i = d3.bisect(d3_time_scaleSteps, target); - if (i == d3_time_scaleSteps.length) return methods.year(extent, m); - if (!i) return linear.ticks(m).map(d3_time_scaleDate); - if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i; - m = methods[i]; - k = m[1]; - m = m[0].range; - } - return m(extent[0], new Date(+extent[1] + 1), k); - }; - scale.tickFormat = function() { - return format; - }; - scale.copy = function() { - return d3_time_scale(linear.copy(), methods, format); - }; - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_time_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; - } - function d3_time_scaleDate(t) { - return new Date(t); - } - function d3_time_scaleFormat(formats) { - return function(date) { - var i = formats.length - 1, f = formats[i]; - while (!f[1](date)) f = formats[--i]; - return f[0](date); - }; - } - function d3_time_scaleSetYear(y) { - var d = new Date(y, 0, 1); - d.setFullYear(y); - return d; - } - function d3_time_scaleGetYear(d) { - var y = d.getFullYear(), d0 = d3_time_scaleSetYear(y), d1 = d3_time_scaleSetYear(y + 1); - return y + (d - d0) / (d1 - d0); - } - 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_scaleLocalFormats = [ [ d3.time.format("%Y"), d3_true ], [ d3.time.format("%B"), function(d) { - return d.getMonth(); - } ], [ d3.time.format("%b %d"), function(d) { - return d.getDate() != 1; - } ], [ d3.time.format("%a %d"), function(d) { - return d.getDay() && d.getDate() != 1; - } ], [ d3.time.format("%I %p"), function(d) { - return d.getHours(); - } ], [ d3.time.format("%I:%M"), function(d) { - return d.getMinutes(); - } ], [ d3.time.format(":%S"), function(d) { - return d.getSeconds(); - } ], [ d3.time.format(".%L"), function(d) { - return d.getMilliseconds(); - } ] ]; - var d3_time_scaleLinear = d3.scale.linear(), d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats); - d3_time_scaleLocalMethods.year = function(extent, m) { - return d3_time_scaleLinear.domain(extent.map(d3_time_scaleGetYear)).ticks(m).map(d3_time_scaleSetYear); - }; - 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_scaleUTCFormats = [ [ d3.time.format.utc("%Y"), d3_true ], [ d3.time.format.utc("%B"), function(d) { - return d.getUTCMonth(); - } ], [ d3.time.format.utc("%b %d"), function(d) { - return d.getUTCDate() != 1; - } ], [ d3.time.format.utc("%a %d"), function(d) { - return d.getUTCDay() && d.getUTCDate() != 1; - } ], [ d3.time.format.utc("%I %p"), function(d) { - return d.getUTCHours(); - } ], [ d3.time.format.utc("%I:%M"), function(d) { - return d.getUTCMinutes(); - } ], [ d3.time.format.utc(":%S"), function(d) { - return d.getUTCSeconds(); - } ], [ d3.time.format.utc(".%L"), function(d) { - return d.getUTCMilliseconds(); - } ] ]; - var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats); - function d3_time_scaleUTCSetYear(y) { - var d = new Date(Date.UTC(y, 0, 1)); - d.setUTCFullYear(y); - return d; - } - function d3_time_scaleUTCGetYear(d) { - var y = d.getUTCFullYear(), d0 = d3_time_scaleUTCSetYear(y), d1 = d3_time_scaleUTCSetYear(y + 1); - return y + (d - d0) / (d1 - d0); - } - d3_time_scaleUTCMethods.year = function(extent, m) { - return d3_time_scaleLinear.domain(extent.map(d3_time_scaleUTCGetYear)).ticks(m).map(d3_time_scaleUTCSetYear); - }; - d3.time.scale.utc = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat); - }; - return d3; -}(); \ No newline at end of file diff --git a/d3/d3.v4.js b/d3/d3.v4.js new file mode 100644 index 0000000..acc598c --- /dev/null +++ b/d3/d3.v4.js @@ -0,0 +1,16383 @@ +// https://d3js.org Version 4.3.0. Copyright 2016 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var version = "4.3.0"; + +var ascending = function(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +}; + +var bisector = function(compare) { + if (compare.length === 1) compare = ascendingComparator(compare); + return { + left: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) 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 (lo == null) lo = 0; + if (hi == null) 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; + } + }; +}; + +function ascendingComparator(f) { + return function(d, x) { + return ascending(f(d), x); + }; +} + +var ascendingBisect = bisector(ascending); +var bisectRight = ascendingBisect.right; +var bisectLeft = ascendingBisect.left; + +var descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +}; + +var number = function(x) { + return x === null ? NaN : +x; +}; + +var variance = function(array, f) { + var n = array.length, + m = 0, + a, + d, + s = 0, + i = -1, + j = 0; + + if (f == null) { + while (++i < n) { + if (!isNaN(a = number(array[i]))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } + + else { + while (++i < n) { + if (!isNaN(a = number(f(array[i], i, array)))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } + + if (j > 1) return s / (j - 1); +}; + +var deviation = function(array, f) { + var v = variance(array, f); + return v ? Math.sqrt(v) : v; +}; + +var extent = function(array, f) { + var i = -1, + n = array.length, + a, + b, + c; + + if (f == null) { + 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(array[i], i, array)) != null && b >= b) { a = c = b; break; } + while (++i < n) if ((b = f(array[i], i, array)) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } + + return [a, c]; +}; + +var array = Array.prototype; + +var slice = array.slice; +var map = array.map; + +var constant$1 = function(x) { + return function() { + return x; + }; +}; + +var identity = function(x) { + return x; +}; + +var range = function(start, stop, step) { + start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; + + var i = -1, + n = Math.max(0, Math.ceil((stop - start) / step)) | 0, + range = new Array(n); + + while (++i < n) { + range[i] = start + i * step; + } + + return range; +}; + +var e10 = Math.sqrt(50); +var e5 = Math.sqrt(10); +var e2 = Math.sqrt(2); + +var ticks = function(start, stop, count) { + var step = tickStep(start, stop, count); + return range( + Math.ceil(start / step) * step, + Math.floor(stop / step) * step + step / 2, // inclusive + step + ); +}; + +function tickStep(start, stop, count) { + var step0 = Math.abs(stop - start) / Math.max(0, count), + step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), + error = step0 / step1; + if (error >= e10) step1 *= 10; + else if (error >= e5) step1 *= 5; + else if (error >= e2) step1 *= 2; + return stop < start ? -step1 : step1; +} + +var sturges = function(values) { + return Math.ceil(Math.log(values.length) / Math.LN2) + 1; +}; + +var histogram = function() { + var value = identity, + domain = extent, + threshold = sturges; + + function histogram(data) { + var i, + n = data.length, + x, + values = new Array(n); + + for (i = 0; i < n; ++i) { + values[i] = value(data[i], i, data); + } + + var xz = domain(values), + x0 = xz[0], + x1 = xz[1], + tz = threshold(values, x0, x1); + + // Convert number of thresholds into uniform thresholds. + if (!Array.isArray(tz)) tz = ticks(x0, x1, tz); + + // Remove any thresholds outside the domain. + var m = tz.length; + while (tz[0] <= x0) tz.shift(), --m; + while (tz[m - 1] >= x1) tz.pop(), --m; + + var bins = new Array(m + 1), + bin; + + // Initialize bins. + for (i = 0; i <= m; ++i) { + bin = bins[i] = []; + bin.x0 = i > 0 ? tz[i - 1] : x0; + bin.x1 = i < m ? tz[i] : x1; + } + + // Assign data to bins by value, ignoring any outside the domain. + for (i = 0; i < n; ++i) { + x = values[i]; + if (x0 <= x && x <= x1) { + bins[bisectRight(tz, x, 0, m)].push(data[i]); + } + } + + return bins; + } + + histogram.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$1(_), histogram) : value; + }; + + histogram.domain = function(_) { + return arguments.length ? (domain = typeof _ === "function" ? _ : constant$1([_[0], _[1]]), histogram) : domain; + }; + + histogram.thresholds = function(_) { + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant$1(slice.call(_)) : constant$1(_), histogram) : threshold; + }; + + return histogram; +}; + +var threshold = function(array, p, f) { + if (f == null) f = number; + if (!(n = array.length)) return; + if ((p = +p) <= 0 || n < 2) return +f(array[0], 0, array); + if (p >= 1) return +f(array[n - 1], n - 1, array); + var n, + h = (n - 1) * p, + i = Math.floor(h), + a = +f(array[i], i, array), + b = +f(array[i + 1], i + 1, array); + return a + (b - a) * (h - i); +}; + +var freedmanDiaconis = function(values, min, max) { + values = map.call(values, number).sort(ascending); + return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3))); +}; + +var scott = function(values, min, max) { + return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); +}; + +var max = function(array, f) { + var i = -1, + n = array.length, + a, + b; + + if (f == null) { + 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(array[i], i, array)) != null && b >= b) { a = b; break; } + while (++i < n) if ((b = f(array[i], i, array)) != null && b > a) a = b; + } + + return a; +}; + +var mean = function(array, f) { + var s = 0, + n = array.length, + a, + i = -1, + j = n; + + if (f == null) { + while (++i < n) if (!isNaN(a = number(array[i]))) s += a; else --j; + } + + else { + while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) s += a; else --j; + } + + if (j) return s / j; +}; + +var median = function(array, f) { + var numbers = [], + n = array.length, + a, + i = -1; + + if (f == null) { + while (++i < n) if (!isNaN(a = number(array[i]))) numbers.push(a); + } + + else { + while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) numbers.push(a); + } + + return threshold(numbers.sort(ascending), 0.5); +}; + +var 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 min = function(array, f) { + var i = -1, + n = array.length, + a, + b; + + if (f == null) { + 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(array[i], i, array)) != null && b >= b) { a = b; break; } + while (++i < n) if ((b = f(array[i], i, array)) != null && a > b) a = b; + } + + return a; +}; + +var pairs = function(array) { + var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = [p, p = array[++i]]; + return pairs; +}; + +var permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; +}; + +var scan = function(array, compare) { + if (!(n = array.length)) return; + var i = 0, + n, + j = 0, + xi, + xj = array[j]; + + if (!compare) compare = ascending; + + while (++i < n) if (compare(xi = array[i], xj) < 0 || compare(xj, xj) !== 0) xj = xi, j = i; + + if (compare(xj, xj) === 0) return j; +}; + +var shuffle = function(array, i0, i1) { + var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +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; +}; + +var sum = function(array, f) { + var s = 0, + n = array.length, + a, + i = -1; + + if (f == null) { + while (++i < n) if (a = +array[i]) s += a; // Note: zero and null are equivalent. + } + + else { + while (++i < n) if (a = +f(array[i], i, array)) s += a; + } + + return s; +}; + +var transpose = function(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { + row[j] = matrix[j][i]; + } + } + return transpose; +}; + +function length(d) { + return d.length; +} + +var zip = function() { + return transpose(arguments); +}; + +var prefix = "$"; + +function Map() {} + +Map.prototype = map$1.prototype = { + constructor: Map, + has: function(key) { + return (prefix + key) in this; + }, + get: function(key) { + return this[prefix + key]; + }, + set: function(key, value) { + this[prefix + key] = value; + return this; + }, + remove: function(key) { + var property = prefix + key; + return property in this && delete this[property]; + }, + clear: function() { + for (var property in this) if (property[0] === prefix) delete this[property]; + }, + keys: function() { + var keys = []; + for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); + return keys; + }, + values: function() { + var values = []; + for (var property in this) if (property[0] === prefix) values.push(this[property]); + return values; + }, + entries: function() { + var entries = []; + for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); + return entries; + }, + size: function() { + var size = 0; + for (var property in this) if (property[0] === prefix) ++size; + return size; + }, + empty: function() { + for (var property in this) if (property[0] === prefix) return false; + return true; + }, + each: function(f) { + for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); + } +}; + +function map$1(object, f) { + var map = new Map; + + // Copy constructor. + if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); + + // Index array by numeric index or specified key function. + else if (Array.isArray(object)) { + var i = -1, + n = object.length, + o; + + if (f == null) while (++i < n) map.set(i, object[i]); + else while (++i < n) map.set(f(o = object[i], i, object), o); + } + + // Convert object to map. + else if (object) for (var key in object) map.set(key, object[key]); + + return map; +} + +var nest = function() { + var keys = [], + sortKeys = [], + sortValues, + rollup, + nest; + + function apply(array, depth, createResult, setResult) { + if (depth >= keys.length) return rollup != null + ? rollup(array) : (sortValues != null + ? array.sort(sortValues) + : array); + + var i = -1, + n = array.length, + key = keys[depth++], + keyValue, + value, + valuesByKey = map$1(), + values, + result = createResult(); + + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { + values.push(value); + } else { + valuesByKey.set(keyValue, [value]); + } + } + + valuesByKey.each(function(values, key) { + setResult(result, key, apply(values, depth, createResult, setResult)); + }); + + return result; + } + + function entries(map, depth) { + if (++depth > keys.length) return map; + var array, sortKey = sortKeys[depth - 1]; + if (rollup != null && depth >= keys.length) array = map.entries(); + else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); + return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; + } + + return nest = { + object: function(array) { return apply(array, 0, createObject, setObject); }, + map: function(array) { return apply(array, 0, createMap, setMap); }, + entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, + key: function(d) { keys.push(d); return nest; }, + sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, + sortValues: function(order) { sortValues = order; return nest; }, + rollup: function(f) { rollup = f; return nest; } + }; +}; + +function createObject() { + return {}; +} + +function setObject(object, key, value) { + object[key] = value; +} + +function createMap() { + return map$1(); +} + +function setMap(map, key, value) { + map.set(key, value); +} + +function Set() {} + +var proto = map$1.prototype; + +Set.prototype = set.prototype = { + constructor: Set, + has: proto.has, + add: function(value) { + value += ""; + this[prefix + value] = value; + return this; + }, + remove: proto.remove, + clear: proto.clear, + values: proto.keys, + size: proto.size, + empty: proto.empty, + each: proto.each +}; + +function set(object, f) { + var set = new Set; + + // Copy constructor. + if (object instanceof Set) object.each(function(value) { set.add(value); }); + + // Otherwise, assume it’s an array. + else if (object) { + var i = -1, n = object.length; + if (f == null) while (++i < n) set.add(object[i]); + else while (++i < n) set.add(f(object[i], i, object)); + } + + return set; +} + +var keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; +}; + +var values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; +}; + +var entries = function(map) { + var entries = []; + for (var key in map) entries.push({key: key, value: map[key]}); + return entries; +}; + +var uniform = function(min, max) { + min = min == null ? 0 : +min; + max = max == null ? 1 : +max; + if (arguments.length === 1) max = min, min = 0; + else max -= min; + return function() { + return Math.random() * max + min; + }; +}; + +var normal = function(mu, sigma) { + var x, r; + mu = mu == null ? 0 : +mu; + sigma = sigma == null ? 1 : +sigma; + return function() { + var y; + + // If available, use the second previously-generated uniform random. + if (x != null) y = x, x = null; + + // Otherwise, generate a new x and y. + else do { + x = Math.random() * 2 - 1; + y = Math.random() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + + return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); + }; +}; + +var logNormal = function() { + var randomNormal = normal.apply(this, arguments); + return function() { + return Math.exp(randomNormal()); + }; +}; + +var irwinHall = function(n) { + return function() { + for (var sum = 0, i = 0; i < n; ++i) sum += Math.random(); + return sum; + }; +}; + +var bates = function(n) { + var randomIrwinHall = irwinHall(n); + return function() { + return randomIrwinHall() / n; + }; +}; + +var exponential = function(lambda) { + return function() { + return -Math.log(1 - Math.random()) / lambda; + }; +}; + +function linear(t) { + return +t; +} + +function quadIn(t) { + return t * t; +} + +function quadOut(t) { + return t * (2 - t); +} + +function quadInOut(t) { + return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; +} + +function cubicIn(t) { + return t * t * t; +} + +function cubicOut(t) { + return --t * t * t + 1; +} + +function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; +} + +var exponent = 3; + +var polyIn = (function custom(e) { + e = +e; + + function polyIn(t) { + return Math.pow(t, e); + } + + polyIn.exponent = custom; + + return polyIn; +})(exponent); + +var polyOut = (function custom(e) { + e = +e; + + function polyOut(t) { + return 1 - Math.pow(1 - t, e); + } + + polyOut.exponent = custom; + + return polyOut; +})(exponent); + +var polyInOut = (function custom(e) { + e = +e; + + function polyInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; + } + + polyInOut.exponent = custom; + + return polyInOut; +})(exponent); + +var pi = Math.PI; +var halfPi = pi / 2; + +function sinIn(t) { + return 1 - Math.cos(t * halfPi); +} + +function sinOut(t) { + return Math.sin(t * halfPi); +} + +function sinInOut(t) { + return (1 - Math.cos(pi * t)) / 2; +} + +function expIn(t) { + return Math.pow(2, 10 * t - 10); +} + +function expOut(t) { + return 1 - Math.pow(2, -10 * t); +} + +function expInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; +} + +function circleIn(t) { + return 1 - Math.sqrt(1 - t * t); +} + +function circleOut(t) { + return Math.sqrt(1 - --t * t); +} + +function circleInOut(t) { + return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; +} + +var b1 = 4 / 11; +var b2 = 6 / 11; +var b3 = 8 / 11; +var b4 = 3 / 4; +var b5 = 9 / 11; +var b6 = 10 / 11; +var b7 = 15 / 16; +var b8 = 21 / 22; +var b9 = 63 / 64; +var b0 = 1 / b1 / b1; + +function bounceIn(t) { + return 1 - bounceOut(1 - t); +} + +function bounceOut(t) { + return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; +} + +function bounceInOut(t) { + return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; +} + +var overshoot = 1.70158; + +var backIn = (function custom(s) { + s = +s; + + function backIn(t) { + return t * t * ((s + 1) * t - s); + } + + backIn.overshoot = custom; + + return backIn; +})(overshoot); + +var backOut = (function custom(s) { + s = +s; + + function backOut(t) { + return --t * t * ((s + 1) * t + s) + 1; + } + + backOut.overshoot = custom; + + return backOut; +})(overshoot); + +var backInOut = (function custom(s) { + s = +s; + + function backInOut(t) { + return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; + } + + backInOut.overshoot = custom; + + return backInOut; +})(overshoot); + +var tau = 2 * Math.PI; +var amplitude = 1; +var period = 0.3; + +var elasticIn = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticIn(t) { + return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); + } + + elasticIn.amplitude = function(a) { return custom(a, p * tau); }; + elasticIn.period = function(p) { return custom(a, p); }; + + return elasticIn; +})(amplitude, period); + +var elasticOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticOut(t) { + return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); + } + + elasticOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticOut.period = function(p) { return custom(a, p); }; + + return elasticOut; +})(amplitude, period); + +var elasticInOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticInOut(t) { + return ((t = t * 2 - 1) < 0 + ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) + : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; + } + + elasticInOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticInOut.period = function(p) { return custom(a, p); }; + + return elasticInOut; +})(amplitude, period); + +var area = function(polygon) { + var i = -1, + n = polygon.length, + a, + b = polygon[n - 1], + area = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + + return area / 2; +}; + +var centroid = function(polygon) { + var i = -1, + n = polygon.length, + x = 0, + y = 0, + a, + b = polygon[n - 1], + c, + k = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + k += c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + + return k *= 3, [x / k, y / k]; +}; + +// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of +// the 3D cross product in a quadrant I Cartesian coordinate system (+x is +// right, +y is up). Returns a positive value if ABC is counter-clockwise, +// negative if clockwise, and zero if the points are collinear. +var cross = function(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); +}; + +function lexicographicOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; +} + +// Computes the upper convex hull per the monotone chain algorithm. +// Assumes points.length >= 3, is sorted by x, unique in y. +// Returns an array of indices into points in left-to-right order. +function computeUpperHullIndexes(points) { + var n = points.length, + indexes = [0, 1], + size = 2; + + for (var i = 2; i < n; ++i) { + while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; + indexes[size++] = i; + } + + return indexes.slice(0, size); // remove popped points +} + +var hull = function(points) { + if ((n = points.length) < 3) return null; + + var i, + n, + sortedPoints = new Array(n), + flippedPoints = new Array(n); + + for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i]; + sortedPoints.sort(lexicographicOrder); + for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; + + var upperIndexes = computeUpperHullIndexes(sortedPoints), + lowerIndexes = computeUpperHullIndexes(flippedPoints); + + // Construct the hull polygon, removing possible duplicate endpoints. + var skipLeft = lowerIndexes[0] === upperIndexes[0], + skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], + hull = []; + + // Add upper hull in right-to-l order. + // Then add lower hull in left-to-right order. + for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]); + for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); + + return hull; +}; + +var contains = function(polygon, point) { + var n = polygon.length, + p = polygon[n - 1], + x = point[0], y = point[1], + x0 = p[0], y0 = p[1], + x1, y1, + inside = false; + + for (var i = 0; i < n; ++i) { + p = polygon[i], x1 = p[0], y1 = p[1]; + if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside; + x0 = x1, y0 = y1; + } + + return inside; +}; + +var length$1 = function(polygon) { + var i = -1, + n = polygon.length, + b = polygon[n - 1], + xa, + ya, + xb = b[0], + yb = b[1], + perimeter = 0; + + while (++i < n) { + xa = xb; + ya = yb; + b = polygon[i]; + xb = b[0]; + yb = b[1]; + xa -= xb; + ya -= yb; + perimeter += Math.sqrt(xa * xa + ya * ya); + } + + return perimeter; +}; + +var pi$1 = Math.PI; +var tau$1 = 2 * pi$1; +var epsilon = 1e-6; +var tauEpsilon = tau$1 - epsilon; + +function Path() { + this._x0 = this._y0 = // start of current subpath + this._x1 = this._y1 = null; // end of current subpath + this._ = []; +} + +function path() { + return new Path; +} + +Path.prototype = path.prototype = { + constructor: Path, + moveTo: function(x, y) { + this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y); + }, + closePath: function() { + if (this._x1 !== null) { + this._x1 = this._x0, this._y1 = this._y0; + this._.push("Z"); + } + }, + lineTo: function(x, y) { + this._.push("L", this._x1 = +x, ",", this._y1 = +y); + }, + quadraticCurveTo: function(x1, y1, x, y) { + this._.push("Q", +x1, ",", +y1, ",", this._x1 = +x, ",", this._y1 = +y); + }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { + this._.push("C", +x1, ",", +y1, ",", +x2, ",", +y2, ",", this._x1 = +x, ",", this._y1 = +y); + }, + arcTo: function(x1, y1, x2, y2, r) { + x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; + var x0 = this._x1, + y0 = this._y1, + x21 = x2 - x1, + y21 = y2 - y1, + x01 = x0 - x1, + y01 = y0 - y1, + l01_2 = x01 * x01 + y01 * y01; + + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x1,y1). + if (this._x1 === null) { + this._.push( + "M", this._x1 = x1, ",", this._y1 = y1 + ); + } + + // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. + else if (!(l01_2 > epsilon)) {} + + // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? + // Equivalently, is (x1,y1) coincident with (x2,y2)? + // Or, is the radius zero? Line to (x1,y1). + else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) { + this._.push( + "L", this._x1 = x1, ",", this._y1 = y1 + ); + } + + // Otherwise, draw an arc! + else { + var x20 = x2 - x0, + y20 = y2 - y0, + l21_2 = x21 * x21 + y21 * y21, + l20_2 = x20 * x20 + y20 * y20, + l21 = Math.sqrt(l21_2), + l01 = Math.sqrt(l01_2), + l = r * Math.tan((pi$1 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), + t01 = l / l01, + t21 = l / l21; + + // If the start tangent is not coincident with (x0,y0), line to. + if (Math.abs(t01 - 1) > epsilon) { + this._.push( + "L", x1 + t01 * x01, ",", y1 + t01 * y01 + ); + } + + this._.push( + "A", r, ",", r, ",0,0,", +(y01 * x20 > x01 * y20), ",", this._x1 = x1 + t21 * x21, ",", this._y1 = y1 + t21 * y21 + ); + } + }, + arc: function(x, y, r, a0, a1, ccw) { + x = +x, y = +y, r = +r; + var dx = r * Math.cos(a0), + dy = r * Math.sin(a0), + x0 = x + dx, + y0 = y + dy, + cw = 1 ^ ccw, + da = ccw ? a0 - a1 : a1 - a0; + + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x0,y0). + if (this._x1 === null) { + this._.push( + "M", x0, ",", y0 + ); + } + + // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). + else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) { + this._.push( + "L", x0, ",", y0 + ); + } + + // Is this arc empty? We’re done. + if (!r) return; + + // Is this a complete circle? Draw two arcs to complete the circle. + if (da > tauEpsilon) { + this._.push( + "A", r, ",", r, ",0,1,", cw, ",", x - dx, ",", y - dy, + "A", r, ",", r, ",0,1,", cw, ",", this._x1 = x0, ",", this._y1 = y0 + ); + } + + // Otherwise, draw an arc! + else { + if (da < 0) da = da % tau$1 + tau$1; + this._.push( + "A", r, ",", r, ",0,", +(da >= pi$1), ",", cw, ",", this._x1 = x + r * Math.cos(a1), ",", this._y1 = y + r * Math.sin(a1) + ); + } + }, + rect: function(x, y, w, h) { + this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y, "h", +w, "v", +h, "h", -w, "Z"); + }, + toString: function() { + return this._.join(""); + } +}; + +var tree_add = function(d) { + var x = +this._x.call(null, d), + y = +this._y.call(null, d); + return add(this.cover(x, y), x, y, d); +}; + +function add(tree, x, y, d) { + if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + x1 = tree._x1, + y1 = tree._y1, + xm, + ym, + xp, + yp, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; +} + +function addAll(data) { + var d, i, n = data.length, + x, + y, + xz = new Array(n), + yz = new Array(n), + x0 = Infinity, + y0 = Infinity, + x1 = -Infinity, + y1 = -Infinity; + + // Compute the points and their extent. + for (i = 0; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; + xz[i] = x; + yz[i] = y; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; + } + + // If there were no (valid) points, inherit the existing extent. + if (x1 < x0) x0 = this._x0, x1 = this._x1; + if (y1 < y0) y0 = this._y0, y1 = this._y1; + + // Expand the tree to cover the new points. + this.cover(x0, y0).cover(x1, y1); + + // Add the new points. + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } + + return this; +} + +var tree_cover = function(x, y) { + if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points + + var x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1; + + // If the quadtree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing quadrant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + } + + // Otherwise, double repeatedly to cover. + else if (x0 > x || x > x1 || y0 > y || y > y1) { + var z = x1 - x0, + node = this._root, + parent, + i; + + switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { + case 0: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); + break; + } + case 1: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); + break; + } + case 2: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); + break; + } + case 3: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); + break; + } + } + + if (this._root && this._root.length) this._root = node; + } + + // If the quadtree covers the point already, just return. + else return this; + + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; +}; + +var tree_data = function() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; +}; + +var tree_extent = function(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; +}; + +var Quad = function(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; +}; + +var tree_find = function(x, y, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + x1, + y1, + x2, + y2, + x3 = this._x1, + y3 = this._y1, + quads = [], + node = this._root, + q, + i; + + if (node) quads.push(new Quad(node, x0, y0, x3, y3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius, y0 = y - radius; + x3 = x + radius, y3 = y + radius; + radius *= radius; + } + + while (q = quads.pop()) { + + // Stop searching if this quadrant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0) continue; + + // Bisect the current quadrant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2; + + quads.push( + new Quad(node[3], xm, ym, x2, y2), + new Quad(node[2], x1, ym, xm, y2), + new Quad(node[1], xm, y1, x2, ym), + new Quad(node[0], x1, y1, xm, ym) + ); + + // Visit the closest quadrant first. + if (i = (y >= ym) << 1 | (x >= xm)) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = node.data; + } + } + } + + return data; +}; + +var tree_remove = function(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1, + x, + y, + xm, + ym, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) + && node === (parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } + + return this; +}; + +function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; +} + +var tree_root = function() { + return this._root; +}; + +var tree_size = function() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; +}; + +var tree_visit = function(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + } + } + return this; +}; + +var tree_visitAfter = function(callback) { + var quads = [], next = [], q; + if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; +}; + +function defaultX(d) { + return d[0]; +} + +var tree_x = function(_) { + return arguments.length ? (this._x = _, this) : this._x; +}; + +function defaultY(d) { + return d[1]; +} + +var tree_y = function(_) { + return arguments.length ? (this._y = _, this) : this._y; +}; + +function quadtree(nodes, x, y) { + var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); +} + +function Quadtree(x, y, x0, y0, x1, y1) { + this._x = x; + this._y = y; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = undefined; +} + +function leaf_copy(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; +} + +var treeProto = quadtree.prototype = Quadtree.prototype; + +treeProto.copy = function() { + var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + node = this._root, + nodes, + child; + + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy(node), copy; + + nodes = [{source: node, target: copy._root = new Array(4)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); + else node.target[i] = leaf_copy(child); + } + } + } + + return copy; +}; + +treeProto.add = tree_add; +treeProto.addAll = addAll; +treeProto.cover = tree_cover; +treeProto.data = tree_data; +treeProto.extent = tree_extent; +treeProto.find = tree_find; +treeProto.remove = tree_remove; +treeProto.removeAll = removeAll; +treeProto.root = tree_root; +treeProto.size = tree_size; +treeProto.visit = tree_visit; +treeProto.visitAfter = tree_visitAfter; +treeProto.x = tree_x; +treeProto.y = tree_y; + +var slice$1 = [].slice; + +var noabort = {}; + +function Queue(size) { + if (!(size >= 1)) throw new Error; + this._size = size; + this._call = + this._error = null; + this._tasks = []; + this._data = []; + this._waiting = + this._active = + this._ended = + this._start = 0; // inside a synchronous task callback? +} + +Queue.prototype = queue.prototype = { + constructor: Queue, + defer: function(callback) { + if (typeof callback !== "function" || this._call) throw new Error; + if (this._error != null) return this; + var t = slice$1.call(arguments, 1); + t.push(callback); + ++this._waiting, this._tasks.push(t); + poke(this); + return this; + }, + abort: function() { + if (this._error == null) abort(this, new Error("abort")); + return this; + }, + await: function(callback) { + if (typeof callback !== "function" || this._call) throw new Error; + this._call = function(error, results) { callback.apply(null, [error].concat(results)); }; + maybeNotify(this); + return this; + }, + awaitAll: function(callback) { + if (typeof callback !== "function" || this._call) throw new Error; + this._call = callback; + maybeNotify(this); + return this; + } +}; + +function poke(q) { + if (!q._start) { + try { start(q); } // let the current task complete + catch (e) { + if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously + else if (!q._data) throw e; // await callback errored synchronously + } + } +} + +function start(q) { + while (q._start = q._waiting && q._active < q._size) { + var i = q._ended + q._active, + t = q._tasks[i], + j = t.length - 1, + c = t[j]; + t[j] = end(q, i); + --q._waiting, ++q._active; + t = c.apply(null, t); + if (!q._tasks[i]) continue; // task finished synchronously + q._tasks[i] = t || noabort; + } +} + +function end(q, i) { + return function(e, r) { + if (!q._tasks[i]) return; // ignore multiple callbacks + --q._active, ++q._ended; + q._tasks[i] = null; + if (q._error != null) return; // ignore secondary errors + if (e != null) { + abort(q, e); + } else { + q._data[i] = r; + if (q._waiting) poke(q); + else maybeNotify(q); + } + }; +} + +function abort(q, e) { + var i = q._tasks.length, t; + q._error = e; // ignore active callbacks + q._data = undefined; // allow gc + q._waiting = NaN; // prevent starting + + while (--i >= 0) { + if (t = q._tasks[i]) { + q._tasks[i] = null; + if (t.abort) { + try { t.abort(); } + catch (e) { /* ignore */ } + } + } + } + + q._active = NaN; // allow notification + maybeNotify(q); +} + +function maybeNotify(q) { + if (!q._active && q._call) { + var d = q._data; + q._data = undefined; // allow gc + q._call(q._error, d); + } +} + +function queue(concurrency) { + return new Queue(arguments.length ? +concurrency : Infinity); +} + +var constant$2 = function(x) { + return function constant() { + return x; + }; +}; + +var epsilon$1 = 1e-12; +var pi$2 = Math.PI; +var halfPi$1 = pi$2 / 2; +var tau$2 = 2 * pi$2; + +function arcInnerRadius(d) { + return d.innerRadius; +} + +function arcOuterRadius(d) { + return d.outerRadius; +} + +function arcStartAngle(d) { + return d.startAngle; +} + +function arcEndAngle(d) { + return d.endAngle; +} + +function arcPadAngle(d) { + return d && d.padAngle; // Note: optional! +} + +function asin(x) { + return x >= 1 ? halfPi$1 : x <= -1 ? -halfPi$1 : Math.asin(x); +} + +function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { + var x10 = x1 - x0, y10 = y1 - y0, + x32 = x3 - x2, y32 = y3 - y2, + t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); + return [x0 + t * x10, y0 + t * y10]; +} + +// Compute perpendicular offset line of length rc. +// http://mathworld.wolfram.com/Circle-LineIntersection.html +function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { + var x01 = x0 - x1, + y01 = y0 - y1, + lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), + ox = lo * y01, + oy = -lo * x01, + x11 = x0 + ox, + y11 = y0 + oy, + x10 = x1 + ox, + y10 = y1 + oy, + x00 = (x11 + x10) / 2, + y00 = (y11 + y10) / 2, + dx = x10 - x11, + dy = y10 - y11, + d2 = dx * dx + dy * dy, + r = r1 - rc, + D = x11 * y10 - x10 * y11, + 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 - x00, + dy0 = cy0 - y00, + dx1 = cx1 - x00, + dy1 = cy1 - y00; + + // Pick the closer of the two intersection points. + // TODO Is there a faster way to determine which intersection to use? + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + + return { + cx: cx0, + cy: cy0, + x01: -ox, + y01: -oy, + x11: cx0 * (r1 / r - 1), + y11: cy0 * (r1 / r - 1) + }; +} + +var arc = function() { + var innerRadius = arcInnerRadius, + outerRadius = arcOuterRadius, + cornerRadius = constant$2(0), + padRadius = null, + startAngle = arcStartAngle, + endAngle = arcEndAngle, + padAngle = arcPadAngle, + context = null; + + function arc() { + var buffer, + r, + r0 = +innerRadius.apply(this, arguments), + r1 = +outerRadius.apply(this, arguments), + a0 = startAngle.apply(this, arguments) - halfPi$1, + a1 = endAngle.apply(this, arguments) - halfPi$1, + da = Math.abs(a1 - a0), + cw = a1 > a0; + + if (!context) context = buffer = path(); + + // Ensure that the outer radius is always larger than the inner radius. + if (r1 < r0) r = r1, r1 = r0, r0 = r; + + // Is it a point? + if (!(r1 > epsilon$1)) context.moveTo(0, 0); + + // Or is it a circle or annulus? + else if (da > tau$2 - epsilon$1) { + context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0)); + context.arc(0, 0, r1, a0, a1, !cw); + if (r0 > epsilon$1) { + context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1)); + context.arc(0, 0, r0, a1, a0, cw); + } + } + + // Or is it a circular or annular sector? + else { + var a01 = a0, + a11 = a1, + a00 = a0, + a10 = a1, + da0 = da, + da1 = da, + ap = padAngle.apply(this, arguments) / 2, + rp = (ap > epsilon$1) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)), + rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), + rc0 = rc, + rc1 = rc, + t0, + t1; + + // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. + if (rp > epsilon$1) { + var p0 = asin(rp / r0 * Math.sin(ap)), + p1 = asin(rp / r1 * Math.sin(ap)); + if ((da0 -= p0 * 2) > epsilon$1) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; + else da0 = 0, a00 = a10 = (a0 + a1) / 2; + if ((da1 -= p1 * 2) > epsilon$1) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; + else da1 = 0, a01 = a11 = (a0 + a1) / 2; + } + + var x01 = r1 * Math.cos(a01), + y01 = r1 * Math.sin(a01), + x10 = r0 * Math.cos(a10), + y10 = r0 * Math.sin(a10); + + // Apply rounded corners? + if (rc > epsilon$1) { + var x11 = r1 * Math.cos(a11), + y11 = r1 * Math.sin(a11), + x00 = r0 * Math.cos(a00), + y00 = r0 * Math.sin(a00); + + // Restrict the corner radius according to the sector angle. + if (da < pi$2) { + var oc = da0 > epsilon$1 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], + ax = x01 - oc[0], + ay = y01 - oc[1], + bx = x11 - oc[0], + by = y11 - 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)); + } + } + + // Is the sector collapsed to a line? + if (!(da1 > epsilon$1)) context.moveTo(x01, y01); + + // Does the sector’s outer ring have rounded corners? + else if (rc1 > epsilon$1) { + t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); + t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); + + context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); + context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); + context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); + } + } + + // Or is the outer ring just a circular arc? + else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); + + // Is there no inner ring, and it’s a circular sector? + // Or perhaps it’s an annular sector collapsed due to padding? + if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10); + + // Does the sector’s inner ring (or point) have rounded corners? + else if (rc0 > epsilon$1) { + t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); + t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); + + context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); + context.arc(0, 0, r0, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); + context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); + } + } + + // Or is the inner ring just a circular arc? + else context.arc(0, 0, r0, a10, a00, cw); + } + + context.closePath(); + + if (buffer) return context = null, buffer + "" || null; + } + + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, + a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$2 / 2; + return [Math.cos(a) * r, Math.sin(a) * r]; + }; + + arc.innerRadius = function(_) { + return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : innerRadius; + }; + + arc.outerRadius = function(_) { + return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : outerRadius; + }; + + arc.cornerRadius = function(_) { + return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : cornerRadius; + }; + + arc.padRadius = function(_) { + return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), arc) : padRadius; + }; + + arc.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : startAngle; + }; + + arc.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : endAngle; + }; + + arc.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : padAngle; + }; + + arc.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), arc) : context; + }; + + return arc; +}; + +function Linear(context) { + this._context = context; +} + +Linear.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: this._context.lineTo(x, y); break; + } + } +}; + +var curveLinear = function(context) { + return new Linear(context); +}; + +function x(p) { + return p[0]; +} + +function y(p) { + return p[1]; +} + +var line = function() { + var x$$1 = x, + y$$1 = y, + defined = constant$2(true), + context = null, + curve = curveLinear, + output = null; + + function line(data) { + var i, + n = data.length, + d, + defined0 = false, + buffer; + + if (context == null) output = curve(buffer = path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) output.lineStart(); + else output.lineEnd(); + } + if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); + } + + if (buffer) return output = null, buffer + "" || null; + } + + line.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : x$$1; + }; + + line.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : y$$1; + }; + + line.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), line) : defined; + }; + + line.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; + }; + + line.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; + }; + + return line; +}; + +var area$1 = function() { + var x0 = x, + x1 = null, + y0 = constant$2(0), + y1 = y, + defined = constant$2(true), + context = null, + curve = curveLinear, + output = null; + + function area(data) { + var i, + j, + k, + n = data.length, + d, + defined0 = false, + buffer, + x0z = new Array(n), + y0z = new Array(n); + + if (context == null) output = curve(buffer = path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) { + j = i; + output.areaStart(); + output.lineStart(); + } else { + output.lineEnd(); + output.lineStart(); + for (k = i - 1; k >= j; --k) { + output.point(x0z[k], y0z[k]); + } + output.lineEnd(); + output.areaEnd(); + } + } + if (defined0) { + x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); + output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); + } + } + + if (buffer) return output = null, buffer + "" || null; + } + + function arealine() { + return line().defined(defined).curve(curve).context(context); + } + + area.x = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), x1 = null, area) : x0; + }; + + area.x0 = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), area) : x0; + }; + + area.x1 = function(_) { + return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : x1; + }; + + area.y = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), y1 = null, area) : y0; + }; + + area.y0 = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), area) : y0; + }; + + area.y1 = function(_) { + return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : y1; + }; + + area.lineX0 = + area.lineY0 = function() { + return arealine().x(x0).y(y0); + }; + + area.lineY1 = function() { + return arealine().x(x0).y(y1); + }; + + area.lineX1 = function() { + return arealine().x(x1).y(y0); + }; + + area.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), area) : defined; + }; + + area.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; + }; + + area.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; + }; + + return area; +}; + +var descending$1 = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +}; + +var identity$1 = function(d) { + return d; +}; + +var pie = function() { + var value = identity$1, + sortValues = descending$1, + sort = null, + startAngle = constant$2(0), + endAngle = constant$2(tau$2), + padAngle = constant$2(0); + + function pie(data) { + var i, + n = data.length, + j, + k, + sum = 0, + index = new Array(n), + arcs = new Array(n), + a0 = +startAngle.apply(this, arguments), + da = Math.min(tau$2, Math.max(-tau$2, endAngle.apply(this, arguments) - a0)), + a1, + p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), + pa = p * (da < 0 ? -1 : 1), + v; + + for (i = 0; i < n; ++i) { + if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { + sum += v; + } + } + + // Optionally sort the arcs by previously-computed values or by data. + if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); + else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); + + // Compute the arcs! They are stored in the original data's order. + for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { + j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { + data: data[j], + index: i, + value: v, + startAngle: a0, + endAngle: a1, + padAngle: p + }; + } + + return arcs; + } + + pie.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), pie) : value; + }; + + pie.sortValues = function(_) { + return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; + }; + + pie.sort = function(_) { + return arguments.length ? (sort = _, sortValues = null, pie) : sort; + }; + + pie.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : startAngle; + }; + + pie.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : endAngle; + }; + + pie.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : padAngle; + }; + + return pie; +}; + +var curveRadialLinear = curveRadial(curveLinear); + +function Radial(curve) { + this._curve = curve; +} + +Radial.prototype = { + areaStart: function() { + this._curve.areaStart(); + }, + areaEnd: function() { + this._curve.areaEnd(); + }, + lineStart: function() { + this._curve.lineStart(); + }, + lineEnd: function() { + this._curve.lineEnd(); + }, + point: function(a, r) { + this._curve.point(r * Math.sin(a), r * -Math.cos(a)); + } +}; + +function curveRadial(curve) { + + function radial(context) { + return new Radial(curve(context)); + } + + radial._curve = curve; + + return radial; +} + +function radialLine(l) { + var c = l.curve; + + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + + l.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return l; +} + +var radialLine$1 = function() { + return radialLine(line().curve(curveRadialLinear)); +}; + +var radialArea = function() { + var a = area$1().curve(curveRadialLinear), + c = a.curve, + x0 = a.lineX0, + x1 = a.lineX1, + y0 = a.lineY0, + y1 = a.lineY1; + + a.angle = a.x, delete a.x; + a.startAngle = a.x0, delete a.x0; + a.endAngle = a.x1, delete a.x1; + a.radius = a.y, delete a.y; + a.innerRadius = a.y0, delete a.y0; + a.outerRadius = a.y1, delete a.y1; + a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0; + a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1; + a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0; + a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1; + + a.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return a; +}; + +var circle = { + draw: function(context, size) { + var r = Math.sqrt(size / pi$2); + context.moveTo(r, 0); + context.arc(0, 0, r, 0, tau$2); + } +}; + +var cross$1 = { + draw: function(context, size) { + var r = Math.sqrt(size / 5) / 2; + context.moveTo(-3 * r, -r); + context.lineTo(-r, -r); + context.lineTo(-r, -3 * r); + context.lineTo(r, -3 * r); + context.lineTo(r, -r); + context.lineTo(3 * r, -r); + context.lineTo(3 * r, r); + context.lineTo(r, r); + context.lineTo(r, 3 * r); + context.lineTo(-r, 3 * r); + context.lineTo(-r, r); + context.lineTo(-3 * r, r); + context.closePath(); + } +}; + +var tan30 = Math.sqrt(1 / 3); +var tan30_2 = tan30 * 2; + +var diamond = { + draw: function(context, size) { + var y = Math.sqrt(size / tan30_2), + x = y * tan30; + context.moveTo(0, -y); + context.lineTo(x, 0); + context.lineTo(0, y); + context.lineTo(-x, 0); + context.closePath(); + } +}; + +var ka = 0.89081309152928522810; +var kr = Math.sin(pi$2 / 10) / Math.sin(7 * pi$2 / 10); +var kx = Math.sin(tau$2 / 10) * kr; +var ky = -Math.cos(tau$2 / 10) * kr; + +var star = { + draw: function(context, size) { + var r = Math.sqrt(size * ka), + x = kx * r, + y = ky * r; + context.moveTo(0, -r); + context.lineTo(x, y); + for (var i = 1; i < 5; ++i) { + var a = tau$2 * i / 5, + c = Math.cos(a), + s = Math.sin(a); + context.lineTo(s * r, -c * r); + context.lineTo(c * x - s * y, s * x + c * y); + } + context.closePath(); + } +}; + +var square = { + draw: function(context, size) { + var w = Math.sqrt(size), + x = -w / 2; + context.rect(x, x, w, w); + } +}; + +var sqrt3 = Math.sqrt(3); + +var triangle = { + draw: function(context, size) { + var y = -Math.sqrt(size / (sqrt3 * 3)); + context.moveTo(0, y * 2); + context.lineTo(-sqrt3 * y, -y); + context.lineTo(sqrt3 * y, -y); + context.closePath(); + } +}; + +var c = -0.5; +var s = Math.sqrt(3) / 2; +var k = 1 / Math.sqrt(12); +var a = (k / 2 + 1) * 3; + +var wye = { + draw: function(context, size) { + var r = Math.sqrt(size / a), + x0 = r / 2, + y0 = r * k, + x1 = x0, + y1 = r * k + r, + x2 = -x1, + y2 = y1; + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + context.lineTo(c * x0 - s * y0, s * x0 + c * y0); + context.lineTo(c * x1 - s * y1, s * x1 + c * y1); + context.lineTo(c * x2 - s * y2, s * x2 + c * y2); + context.lineTo(c * x0 + s * y0, c * y0 - s * x0); + context.lineTo(c * x1 + s * y1, c * y1 - s * x1); + context.lineTo(c * x2 + s * y2, c * y2 - s * x2); + context.closePath(); + } +}; + +var symbols = [ + circle, + cross$1, + diamond, + square, + star, + triangle, + wye +]; + +var symbol = function() { + var type = constant$2(circle), + size = constant$2(64), + context = null; + + function symbol() { + var buffer; + if (!context) context = buffer = path(); + type.apply(this, arguments).draw(context, +size.apply(this, arguments)); + if (buffer) return context = null, buffer + "" || null; + } + + symbol.type = function(_) { + return arguments.length ? (type = typeof _ === "function" ? _ : constant$2(_), symbol) : type; + }; + + symbol.size = function(_) { + return arguments.length ? (size = typeof _ === "function" ? _ : constant$2(+_), symbol) : size; + }; + + symbol.context = function(_) { + return arguments.length ? (context = _ == null ? null : _, symbol) : context; + }; + + return symbol; +}; + +var noop = function() {}; + +function point(that, x, y) { + that._context.bezierCurveTo( + (2 * that._x0 + that._x1) / 3, + (2 * that._y0 + that._y1) / 3, + (that._x0 + 2 * that._x1) / 3, + (that._y0 + 2 * that._y1) / 3, + (that._x0 + 4 * that._x1 + x) / 6, + (that._y0 + 4 * that._y1 + y) / 6 + ); +} + +function Basis(context) { + this._context = context; +} + +Basis.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 3: point(this, this._x1, this._y1); // proceed + case 2: this._context.lineTo(this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basis = function(context) { + return new Basis(context); +}; + +function BasisClosed(context) { + this._context = context; +} + +BasisClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x2, this._y2); + this._context.closePath(); + break; + } + case 2: { + this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); + this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x2, this._y2); + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x2 = x, this._y2 = y; break; + case 1: this._point = 2; this._x3 = x, this._y3 = y; break; + case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basisClosed = function(context) { + return new BasisClosed(context); +}; + +function BasisOpen(context) { + this._context = context; +} + +BasisOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; + case 3: this._point = 4; // proceed + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basisOpen = function(context) { + return new BasisOpen(context); +}; + +function Bundle(context, beta) { + this._basis = new Basis(context); + this._beta = beta; +} + +Bundle.prototype = { + lineStart: function() { + this._x = []; + this._y = []; + this._basis.lineStart(); + }, + lineEnd: function() { + var x = this._x, + y = this._y, + j = x.length - 1; + + if (j > 0) { + var x0 = x[0], + y0 = y[0], + dx = x[j] - x0, + dy = y[j] - y0, + i = -1, + t; + + while (++i <= j) { + t = i / j; + this._basis.point( + this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), + this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) + ); + } + } + + this._x = this._y = null; + this._basis.lineEnd(); + }, + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } +}; + +var bundle = (function custom(beta) { + + function bundle(context) { + return beta === 1 ? new Basis(context) : new Bundle(context, beta); + } + + bundle.beta = function(beta) { + return custom(+beta); + }; + + return bundle; +})(0.85); + +function point$1(that, x, y) { + that._context.bezierCurveTo( + that._x1 + that._k * (that._x2 - that._x0), + that._y1 + that._k * (that._y2 - that._y0), + that._x2 + that._k * (that._x1 - x), + that._y2 + that._k * (that._y1 - y), + that._x2, + that._y2 + ); +} + +function Cardinal(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +Cardinal.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: point$1(this, this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; this._x1 = x, this._y1 = y; break; + case 2: this._point = 3; // proceed + default: point$1(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinal = (function custom(tension) { + + function cardinal(context) { + return new Cardinal(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +})(0); + +function CardinalClosed(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$1(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinalClosed = (function custom(tension) { + + function cardinal(context) { + return new CardinalClosed(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +})(0); + +function CardinalOpen(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$1(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinalOpen = (function custom(tension) { + + function cardinal(context) { + return new CardinalOpen(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +})(0); + +function point$2(that, x, y) { + var x1 = that._x1, + y1 = that._y1, + x2 = that._x2, + y2 = that._y2; + + if (that._l01_a > epsilon$1) { + var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, + n = 3 * that._l01_a * (that._l01_a + that._l12_a); + x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; + y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; + } + + if (that._l23_a > epsilon$1) { + var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, + m = 3 * that._l23_a * (that._l23_a + that._l12_a); + x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; + y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; + } + + that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); +} + +function CatmullRom(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRom.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: this.point(this._x2, this._y2); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; // proceed + default: point$2(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRom = (function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +})(0.5); + +function CatmullRomClosed(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRomClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$2(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRomClosed = (function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +})(0.5); + +function CatmullRomOpen(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRomOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$2(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRomOpen = (function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +})(0.5); + +function LinearClosed(context) { + this._context = context; +} + +LinearClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._point) this._context.closePath(); + }, + point: function(x, y) { + x = +x, y = +y; + if (this._point) this._context.lineTo(x, y); + else this._point = 1, this._context.moveTo(x, y); + } +}; + +var linearClosed = function(context) { + return new LinearClosed(context); +}; + +function sign(x) { + return x < 0 ? -1 : 1; +} + +// Calculate the slopes of the tangents (Hermite-type interpolation) based on +// the following paper: Steffen, M. 1990. A Simple Method for Monotonic +// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. +// NOV(II), P. 443, 1990. +function slope3(that, x2, y2) { + var h0 = that._x1 - that._x0, + h1 = x2 - that._x1, + s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), + s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), + p = (s0 * h1 + s1 * h0) / (h0 + h1); + return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; +} + +// Calculate a one-sided slope. +function slope2(that, t) { + var h = that._x1 - that._x0; + return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; +} + +// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations +// "you can express cubic Hermite interpolation in terms of cubic Bézier curves +// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". +function point$3(that, t0, t1) { + var x0 = that._x0, + y0 = that._y0, + x1 = that._x1, + y1 = that._y1, + dx = (x1 - x0) / 3; + that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); +} + +function MonotoneX(context) { + this._context = context; +} + +MonotoneX.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = + this._t0 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x1, this._y1); break; + case 3: point$3(this, this._t0, slope2(this, this._t0)); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + var t1 = NaN; + + x = +x, y = +y; + if (x === this._x1 && y === this._y1) return; // Ignore coincident points. + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break; + default: point$3(this, this._t0, t1 = slope3(this, x, y)); break; + } + + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + this._t0 = t1; + } +}; + +function MonotoneY(context) { + this._context = new ReflectContext(context); +} + +(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { + MonotoneX.prototype.point.call(this, y, x); +}; + +function ReflectContext(context) { + this._context = context; +} + +ReflectContext.prototype = { + moveTo: function(x, y) { this._context.moveTo(y, x); }, + closePath: function() { this._context.closePath(); }, + lineTo: function(x, y) { this._context.lineTo(y, x); }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } +}; + +function monotoneX(context) { + return new MonotoneX(context); +} + +function monotoneY(context) { + return new MonotoneY(context); +} + +function Natural(context) { + this._context = context; +} + +Natural.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x = []; + this._y = []; + }, + lineEnd: function() { + var x = this._x, + y = this._y, + n = x.length; + + if (n) { + this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); + if (n === 2) { + this._context.lineTo(x[1], y[1]); + } else { + var px = controlPoints(x), + py = controlPoints(y); + for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { + this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); + } + } + } + + if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); + this._line = 1 - this._line; + this._x = this._y = null; + }, + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } +}; + +// See https://www.particleincell.com/2012/bezier-splines/ for derivation. +function controlPoints(x) { + var i, + n = x.length - 1, + m, + a = new Array(n), + b = new Array(n), + r = new Array(n); + a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; + for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; + a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; + for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; + a[n - 1] = r[n - 1] / b[n - 1]; + for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; + b[n - 1] = (x[n] + a[n - 1]) / 2; + for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; + return [a, b]; +} + +var natural = function(context) { + return new Natural(context); +}; + +function Step(context, t) { + this._context = context; + this._t = t; +} + +Step.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x = this._y = NaN; + this._point = 0; + }, + lineEnd: function() { + if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: { + if (this._t <= 0) { + this._context.lineTo(this._x, y); + this._context.lineTo(x, y); + } else { + var x1 = this._x * (1 - this._t) + x * this._t; + this._context.lineTo(x1, this._y); + this._context.lineTo(x1, y); + } + break; + } + } + this._x = x, this._y = y; + } +}; + +var step = function(context) { + return new Step(context, 0.5); +}; + +function stepBefore(context) { + return new Step(context, 0); +} + +function stepAfter(context) { + return new Step(context, 1); +} + +var slice$2 = Array.prototype.slice; + +var none = function(series, order) { + if (!((n = series.length) > 1)) return; + for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { + s0 = s1, s1 = series[order[i]]; + for (var j = 0; j < m; ++j) { + s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; + } + } +}; + +var none$1 = function(series) { + var n = series.length, o = new Array(n); + while (--n >= 0) o[n] = n; + return o; +}; + +function stackValue(d, key) { + return d[key]; +} + +var stack = function() { + var keys = constant$2([]), + order = none$1, + offset = none, + value = stackValue; + + function stack(data) { + var kz = keys.apply(this, arguments), + i, + m = data.length, + n = kz.length, + sz = new Array(n), + oz; + + for (i = 0; i < n; ++i) { + for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { + si[j] = sij = [0, +value(data[j], ki, j, data)]; + sij.data = data[j]; + } + si.key = ki; + } + + for (i = 0, oz = order(sz); i < n; ++i) { + sz[oz[i]].index = i; + } + + offset(sz, oz); + return sz; + } + + stack.keys = function(_) { + return arguments.length ? (keys = typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : keys; + }; + + stack.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), stack) : value; + }; + + stack.order = function(_) { + return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : order; + }; + + stack.offset = function(_) { + return arguments.length ? (offset = _ == null ? none : _, stack) : offset; + }; + + return stack; +}; + +var expand = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { + for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; + if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; + } + none(series, order); +}; + +var silhouette = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { + for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; + s0[j][1] += s0[j][0] = -y / 2; + } + none(series, order); +}; + +var wiggle = function(series, order) { + if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; + for (var y = 0, j = 1, s0, m, n; j < m; ++j) { + for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { + var si = series[order[i]], + sij0 = si[j][1] || 0, + sij1 = si[j - 1][1] || 0, + s3 = (sij0 - sij1) / 2; + for (var k = 0; k < i; ++k) { + var sk = series[order[k]], + skj0 = sk[j][1] || 0, + skj1 = sk[j - 1][1] || 0; + s3 += skj0 - skj1; + } + s1 += sij0, s2 += s3 * sij0; + } + s0[j - 1][1] += s0[j - 1][0] = y; + if (s1) y -= s2 / s1; + } + s0[j - 1][1] += s0[j - 1][0] = y; + none(series, order); +}; + +var ascending$1 = function(series) { + var sums = series.map(sum$1); + return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; }); +}; + +function sum$1(series) { + var s = 0, i = -1, n = series.length, v; + while (++i < n) if (v = +series[i][1]) s += v; + return s; +} + +var descending$2 = function(series) { + return ascending$1(series).reverse(); +}; + +var insideOut = function(series) { + var n = series.length, + i, + j, + sums = series.map(sum$1), + order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }), + top = 0, + bottom = 0, + tops = [], + bottoms = []; + + for (i = 0; i < n; ++i) { + j = order[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + + return bottoms.reverse().concat(tops); +}; + +var reverse = function(series) { + return none$1(series).reverse(); +}; + +var define = function(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; +}; + +function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) prototype[key] = definition[key]; + return prototype; +} + +function Color() {} + +var darker = 0.7; +var brighter = 1 / darker; + +var reHex3 = /^#([0-9a-f]{3})$/; +var reHex6 = /^#([0-9a-f]{6})$/; +var reRgbInteger = /^rgb\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*\)$/; +var reRgbPercent = /^rgb\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/; +var reRgbaInteger = /^rgba\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/; +var reRgbaPercent = /^rgba\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/; +var reHslPercent = /^hsl\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/; +var reHslaPercent = /^hsla\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/; + +var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 +}; + +define(Color, color, { + displayable: function() { + return this.rgb().displayable(); + }, + toString: function() { + return this.rgb() + ""; + } +}); + +function color(format) { + var m; + format = (format + "").trim().toLowerCase(); + return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 + : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; +} + +function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); +} + +function rgba(r, g, b, a) { + if (a <= 0) r = g = b = NaN; + return new Rgb(r, g, b, a); +} + +function rgbConvert(o) { + if (!(o instanceof Color)) o = color(o); + if (!o) return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); +} + +function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); +} + +function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; +} + +define(Rgb, rgb, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb: function() { + return this; + }, + displayable: function() { + return (0 <= this.r && this.r <= 255) + && (0 <= this.g && this.g <= 255) + && (0 <= this.b && this.b <= 255) + && (0 <= this.opacity && this.opacity <= 1); + }, + toString: function() { + var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "rgb(" : "rgba(") + + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + + (a === 1 ? ")" : ", " + a + ")"); + } +})); + +function hsla(h, s, l, a) { + if (a <= 0) h = s = l = NaN; + else if (l <= 0 || l >= 1) h = s = NaN; + else if (s <= 0) h = NaN; + return new Hsl(h, s, l, a); +} + +function hslConvert(o) { + if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) o = color(o); + if (!o) return new Hsl; + if (o instanceof Hsl) return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) h = (g - b) / s + (g < b) * 6; + else if (g === max) h = (b - r) / s + 2; + else h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); +} + +function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); +} + +function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Hsl, hsl, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); + }, + displayable: function() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + } +})); + +/* From FvD 13.37, CSS Color Module Level 3 */ +function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; +} + +var deg2rad = Math.PI / 180; +var rad2deg = 180 / Math.PI; + +var Kn = 18; +var Xn = 0.950470; +var Yn = 1; +var Zn = 1.088830; +var t0 = 4 / 29; +var t1 = 6 / 29; +var t2 = 3 * t1 * t1; +var t3 = t1 * t1 * t1; + +function labConvert(o) { + if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); + if (o instanceof Hcl) { + var h = o.h * deg2rad; + return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); + } + if (!(o instanceof Rgb)) o = rgbConvert(o); + var b = rgb2xyz(o.r), + a = rgb2xyz(o.g), + l = rgb2xyz(o.b), + x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), + y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), + z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); + return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); +} + +function lab(l, a, b, opacity) { + return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); +} + +function Lab(l, a, b, opacity) { + this.l = +l; + this.a = +a; + this.b = +b; + this.opacity = +opacity; +} + +define(Lab, lab, extend(Color, { + brighter: function(k) { + return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + darker: function(k) { + return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + rgb: function() { + var y = (this.l + 16) / 116, + x = isNaN(this.a) ? y : y + this.a / 500, + z = isNaN(this.b) ? y : y - this.b / 200; + y = Yn * lab2xyz(y); + x = Xn * lab2xyz(x); + z = Zn * lab2xyz(z); + return new Rgb( + xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB + xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), + xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), + this.opacity + ); + } +})); + +function xyz2lab(t) { + return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; +} + +function lab2xyz(t) { + return t > t1 ? t * t * t : t2 * (t - t0); +} + +function xyz2rgb(x) { + return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); +} + +function rgb2xyz(x) { + return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); +} + +function hclConvert(o) { + if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); + if (!(o instanceof Lab)) o = labConvert(o); + var h = Math.atan2(o.b, o.a) * rad2deg; + return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); +} + +function hcl(h, c, l, opacity) { + return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); +} + +function Hcl(h, c, l, opacity) { + this.h = +h; + this.c = +c; + this.l = +l; + this.opacity = +opacity; +} + +define(Hcl, hcl, extend(Color, { + brighter: function(k) { + return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); + }, + darker: function(k) { + return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); + }, + rgb: function() { + return labConvert(this).rgb(); + } +})); + +var A = -0.14861; +var B = +1.78277; +var C = -0.29227; +var D = -0.90649; +var E = +1.97294; +var ED = E * D; +var EB = E * B; +var BC_DA = B * C - D * A; + +function cubehelixConvert(o) { + if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Rgb)) o = rgbConvert(o); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), + bl = b - l, + k = (E * (g - l) - C * bl) / D, + s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 + h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; + return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); +} + +function cubehelix(h, s, l, opacity) { + return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); +} + +function Cubehelix(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Cubehelix, cubehelix, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, + l = +this.l, + a = isNaN(this.s) ? 0 : this.s * l * (1 - l), + cosh = Math.cos(h), + sinh = Math.sin(h); + return new Rgb( + 255 * (l + a * (A * cosh + B * sinh)), + 255 * (l + a * (C * cosh + D * sinh)), + 255 * (l + a * (E * cosh)), + this.opacity + ); + } +})); + +function basis$1(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + + (4 - 6 * t2 + 3 * t3) * v1 + + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + + t3 * v3) / 6; +} + +var basis$2 = function(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), + v1 = values[i], + v2 = values[i + 1], + v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, + v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis$1((t - i / n) * n, v0, v1, v2, v3); + }; +}; + +var basisClosed$1 = function(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), + v0 = values[(i + n - 1) % n], + v1 = values[i % n], + v2 = values[(i + 1) % n], + v3 = values[(i + 2) % n]; + return basis$1((t - i / n) * n, v0, v1, v2, v3); + }; +}; + +var constant$3 = function(x) { + return function() { + return x; + }; +}; + +function linear$1(a, d) { + return function(t) { + return a + t * d; + }; +} + +function exponential$1(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { + return Math.pow(a + t * b, y); + }; +} + +function hue(a, b) { + var d = b - a; + return d ? linear$1(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a); +} + +function gamma(y) { + return (y = +y) === 1 ? nogamma : function(a, b) { + return b - a ? exponential$1(a, b, y) : constant$3(isNaN(a) ? b : a); + }; +} + +function nogamma(a, b) { + var d = b - a; + return d ? linear$1(a, d) : constant$3(isNaN(a) ? b : a); +} + +var interpolateRgb = (function rgbGamma(y) { + var color$$1 = gamma(y); + + function rgb$$1(start, end) { + var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r), + g = color$$1(start.g, end.g), + b = color$$1(start.b, end.b), + opacity = color$$1(start.opacity, end.opacity); + return function(t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + rgb$$1.gamma = rgbGamma; + + return rgb$$1; +})(1); + +function rgbSpline(spline) { + return function(colors) { + var n = colors.length, + r = new Array(n), + g = new Array(n), + b = new Array(n), + i, color$$1; + for (i = 0; i < n; ++i) { + color$$1 = rgb(colors[i]); + r[i] = color$$1.r || 0; + g[i] = color$$1.g || 0; + b[i] = color$$1.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color$$1.opacity = 1; + return function(t) { + color$$1.r = r(t); + color$$1.g = g(t); + color$$1.b = b(t); + return color$$1 + ""; + }; + }; +} + +var rgbBasis = rgbSpline(basis$2); +var rgbBasisClosed = rgbSpline(basisClosed$1); + +var array$1 = function(a, b) { + var nb = b ? b.length : 0, + na = a ? Math.min(nb, a.length) : 0, + x = new Array(nb), + c = new Array(nb), + i; + + for (i = 0; i < na; ++i) x[i] = interpolate(a[i], b[i]); + for (; i < nb; ++i) c[i] = b[i]; + + return function(t) { + for (i = 0; i < na; ++i) c[i] = x[i](t); + return c; + }; +}; + +var date = function(a, b) { + var d = new Date; + return a = +a, b -= a, function(t) { + return d.setTime(a + b * t), d; + }; +}; + +var interpolateNumber = function(a, b) { + return a = +a, b -= a, function(t) { + return a + b * t; + }; +}; + +var object = function(a, b) { + var i = {}, + c = {}, + k; + + if (a === null || typeof a !== "object") a = {}; + if (b === null || typeof b !== "object") b = {}; + + for (k in b) { + if (k in a) { + i[k] = interpolate(a[k], b[k]); + } else { + c[k] = b[k]; + } + } + + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; +}; + +var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; +var reB = new RegExp(reA.source, "g"); + +function zero(b) { + return function() { + return b; + }; +} + +function one(b) { + return function(t) { + return b(t) + ""; + }; +} + +var interpolateString = function(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators + + // Coerce inputs to strings. + a = a + "", b = b + ""; + + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) s[i] += bm; // coalesce with previous string + else s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: interpolateNumber(am, bm)}); + } + bi = reB.lastIndex; + } + + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(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 interpolate = function(a, b) { + var t = typeof b, c; + return b == null || t === "boolean" ? constant$3(b) + : (t === "number" ? interpolateNumber + : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString) + : b instanceof color ? interpolateRgb + : b instanceof Date ? date + : Array.isArray(b) ? array$1 + : isNaN(b) ? object + : interpolateNumber)(a, b); +}; + +var interpolateRound = function(a, b) { + return a = +a, b -= a, function(t) { + return Math.round(a + b * t); + }; +}; + +var degrees = 180 / Math.PI; + +var identity$2 = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 +}; + +var decompose = function(a, b, c, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; + if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; + if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX: scaleX, + scaleY: scaleY + }; +}; + +var cssNode; +var cssRoot; +var cssView; +var svgNode; + +function parseCss(value) { + if (value === "none") return identity$2; + if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; + cssNode.style.transform = value; + value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); + cssRoot.removeChild(cssNode); + value = value.slice(7, -1).split(","); + return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); +} + +function parseSvg(value) { + if (value == null) return identity$2; + if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2; + value = value.matrix; + return decompose(value.a, value.b, value.c, value.d, value.e, value.f); +} + +function interpolateTransform(parse, pxComma, pxParen, degParen) { + + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + + return function(a, b) { + var s = [], // string constants and placeholders + q = []; // number interpolators + a = parse(a), b = parse(b); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); + rotate(a.rotate, b.rotate, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); + a = b = null; // gc + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; +} + +var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); +var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + +var rho = Math.SQRT2; +var rho2 = 2; +var rho4 = 4; +var epsilon2 = 1e-12; + +function cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; +} + +function sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; +} + +function tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); +} + +// p0 = [ux0, uy0, w0] +// p1 = [ux1, uy1, w1] +var 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; + + // Special case for u0 ≅ u1. + if (d2 < epsilon2) { + S = Math.log(w1 / w0) / rho; + i = function(t) { + return [ + ux0 + t * dx, + uy0 + t * dy, + w0 * Math.exp(rho * t * S) + ]; + }; + } + + // General case. + else { + var d1 = Math.sqrt(d2), + b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), + b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), + r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), + r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / rho; + i = function(t) { + var s = t * S, + coshr0 = cosh(r0), + u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); + return [ + ux0 + u * dx, + uy0 + u * dy, + w0 * coshr0 / cosh(rho * s + r0) + ]; + }; + } + + i.duration = S * 1000; + + return i; +}; + +function hsl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hsl$2 = hsl$1(hue); +var hslLong = hsl$1(nogamma); + +function lab$1(start, end) { + var l = nogamma((start = lab(start)).l, (end = lab(end)).l), + a = nogamma(start.a, end.a), + b = nogamma(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.l = l(t); + start.a = a(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; +} + +function hcl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h), + c = nogamma(start.c, end.c), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.c = c(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hcl$2 = hcl$1(hue); +var hclLong = hcl$1(nogamma); + +function cubehelix$1(hue$$1) { + return (function cubehelixGamma(y) { + y = +y; + + function cubehelix$$1(start, end) { + var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(Math.pow(t, y)); + start.opacity = opacity(t); + return start + ""; + }; + } + + cubehelix$$1.gamma = cubehelixGamma; + + return cubehelix$$1; + })(1); +} + +var cubehelix$2 = cubehelix$1(hue); +var cubehelixLong = cubehelix$1(nogamma); + +var quantize = function(interpolator, n) { + var samples = new Array(n); + for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); + return samples; +}; + +var noop$1 = {value: function() {}}; + +function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); +} + +function Dispatch(_) { + this._ = _; +} + +function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); +} + +Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; + + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; + return; + } + + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) _[t] = set$2(_[t], typename.name, callback); + else if (callback == null) for (t in _) _[t] = set$2(_[t], typename.name, null); + } + + return this; + }, + copy: function() { + var copy = {}, _ = this._; + for (var t in _) copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function(type, that) { + if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + }, + apply: function(type, that, args) { + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + } +}; + +function get(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } + } +} + +function set$2(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop$1, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) type.push({name: name, value: callback}); + return type; +} + +function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); +} + +function customConverter(columns, f) { + var object = objectConverter(columns); + return function(row, i) { + return f(object(row), i, columns); + }; +} + +// Compute unique columns in order of discovery. +function inferColumns(rows) { + var columnSet = Object.create(null), + columns = []; + + rows.forEach(function(row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); + + return columns; +} + +var dsv = function(delimiter) { + var reFormat = new RegExp("[\"" + delimiter + "\n]"), + delimiterCode = delimiter.charCodeAt(0); + + function parse(text, f) { + var convert, columns, rows = parseRows(text, function(row, i) { + if (convert) return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns; + return rows; + } + + function parseRows(text, f) { + var EOL = {}, // sentinel value for end-of-line + EOF = {}, // sentinel value for end-of-file + rows = [], // output rows + N = text.length, + I = 0, // current character index + n = 0, // the current line number + t, // the current token + eol; // is the current token followed by EOL? + + function token() { + if (I >= N) return EOF; // special case: end of file + if (eol) return eol = false, EOL; // special case: end of line + + // special case: quotes + var j = I, c; + 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; + 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, "\""); + } + + // common case: find next delimiter or newline + while (I < N) { + var k = 1; + c = text.charCodeAt(I++); + if (c === 10) eol = true; // \n + else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n + else if (c !== delimiterCode) continue; + return text.slice(j, I - k); + } + + // special case: last token before EOF + 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); + } + + return rows; + } + + function format(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { + return columns.map(function(column) { + return formatValue(row[column]); + }).join(delimiter); + })).join("\n"); + } + + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } + + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + + function formatValue(text) { + return text == null ? "" + : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\"" + : text; + } + + return { + parse: parse, + parseRows: parseRows, + format: format, + formatRows: formatRows + }; +}; + +var csv = dsv(","); + +var csvParse = csv.parse; +var csvParseRows = csv.parseRows; +var csvFormat = csv.format; +var csvFormatRows = csv.formatRows; + +var tsv = dsv("\t"); + +var tsvParse = tsv.parse; +var tsvParseRows = tsv.parseRows; +var tsvFormat = tsv.format; +var tsvFormatRows = tsv.formatRows; + +var request = function(url, callback) { + var request, + event = dispatch("beforesend", "progress", "load", "error"), + mimeType, + headers = map$1(), + xhr = new XMLHttpRequest, + user = null, + password = null, + response, + responseType, + timeout = 0; + + // If IE does not support CORS, use XDomainRequest. + if (typeof XDomainRequest !== "undefined" + && !("withCredentials" in xhr) + && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; + + "onload" in xhr + ? xhr.onload = xhr.onerror = xhr.ontimeout = respond + : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; + + function respond(o) { + var status = xhr.status, result; + if (!status && hasResponse(xhr) + || status >= 200 && status < 300 + || status === 304) { + if (response) { + try { + result = response.call(request, xhr); + } catch (e) { + event.call("error", request, e); + return; + } + } else { + result = xhr; + } + event.call("load", request, result); + } else { + event.call("error", request, o); + } + } + + xhr.onprogress = function(e) { + event.call("progress", request, e); + }; + + request = { + header: function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers.get(name); + if (value == null) headers.remove(name); + else headers.set(name, value + ""); + return request; + }, + + // If mimeType is non-null and no Accept header is set, a default is used. + mimeType: function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return request; + }, + + // Specifies what type the response value should take; + // for instance, arraybuffer, blob, document, or text. + responseType: function(value) { + if (!arguments.length) return responseType; + responseType = value; + return request; + }, + + timeout: function(value) { + if (!arguments.length) return timeout; + timeout = +value; + return request; + }, + + user: function(value) { + return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); + }, + + password: function(value) { + return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); + }, + + // Specify how to convert the response content to a specific type; + // changes the callback value on "load" events. + response: function(value) { + response = value; + return request; + }, + + // Alias for send("GET", …). + get: function(data, callback) { + return request.send("GET", data, callback); + }, + + // Alias for send("POST", …). + post: function(data, callback) { + return request.send("POST", data, callback); + }, + + // If callback is non-null, it will be used for error and load events. + send: function(method, data, callback) { + xhr.open(method, url, true, user, password); + if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); + if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); + if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); + if (responseType != null) xhr.responseType = responseType; + if (timeout > 0) xhr.timeout = timeout; + if (callback == null && typeof data === "function") callback = data, data = null; + if (callback != null && callback.length === 1) callback = fixCallback(callback); + if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); + event.call("beforesend", request, xhr); + xhr.send(data == null ? null : data); + return request; + }, + + abort: function() { + xhr.abort(); + return request; + }, + + on: function() { + var value = event.on.apply(event, arguments); + return value === event ? request : value; + } + }; + + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return request.get(callback); + } + + return request; +}; + +function fixCallback(callback) { + return function(error, xhr) { + callback(error == null ? xhr : null); + }; +} + +function hasResponse(xhr) { + var type = xhr.responseType; + return type && type !== "text" + ? xhr.response // null on error + : xhr.responseText; // "" on error +} + +var type = function(defaultMimeType, response) { + return function(url, callback) { + var r = request(url).mimeType(defaultMimeType).response(response); + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return r.get(callback); + } + return r; + }; +}; + +var html = type("text/html", function(xhr) { + return document.createRange().createContextualFragment(xhr.responseText); +}); + +var json = type("application/json", function(xhr) { + return JSON.parse(xhr.responseText); +}); + +var text = type("text/plain", function(xhr) { + return xhr.responseText; +}); + +var xml = type("application/xml", function(xhr) { + var xml = xhr.responseXML; + if (!xml) throw new Error("parse error"); + return xml; +}); + +var dsv$1 = function(defaultMimeType, parse) { + return function(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var r = request(url).mimeType(defaultMimeType); + r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; + r.row(row); + return callback ? r.get(callback) : r; + }; +}; + +function responseOf(parse, row) { + return function(request$$1) { + return parse(request$$1.responseText, row); + }; +} + +var csv$1 = dsv$1("text/csv", csvParse); + +var tsv$1 = dsv$1("text/tab-separated-values", tsvParse); + +var frame = 0; +var timeout = 0; +var interval = 0; +var pokeDelay = 1000; +var taskHead; +var taskTail; +var clockLast = 0; +var clockNow = 0; +var clockSkew = 0; +var clock = typeof performance === "object" && performance.now ? performance : Date; +var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); }; + +function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); +} + +function clearNow() { + clockNow = 0; +} + +function Timer() { + this._call = + this._time = + this._next = null; +} + +Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) taskTail._next = this; + else taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } +}; + +function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; +} + +function timerFlush() { + now(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) t._call.call(null, e); + t = t._next; + } + --frame; +} + +function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } +} + +function poke$1() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) clockSkew -= delay, clockLast = now; +} + +function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); +} + +function sleep(time) { + if (frame) return; // Soonest alarm already set, or will be. + if (timeout) timeout = clearTimeout(timeout); + var delay = time - clockNow; + if (delay > 24) { + if (time < Infinity) timeout = setTimeout(wake, delay); + if (interval) interval = clearInterval(interval); + } else { + if (!interval) interval = setInterval(poke$1, pokeDelay); + frame = 1, setFrame(wake); + } +} + +var timeout$1 = function(callback, delay, time) { + var t = new Timer; + delay = delay == null ? 0 : +delay; + t.restart(function(elapsed) { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; +}; + +var interval$1 = function(callback, delay, time) { + var t = new Timer, total = delay; + if (delay == null) return t.restart(callback, delay, time), t; + delay = +delay, time = time == null ? now() : +time; + t.restart(function tick(elapsed) { + elapsed += total; + t.restart(tick, total += delay, time); + callback(elapsed); + }, delay, time); + return t; +}; + +var t0$1 = new Date; +var t1$1 = new Date; + +function newInterval(floori, offseti, count, field) { + + function interval(date) { + return floori(date = new Date(+date)), date; + } + + interval.floor = interval; + + interval.ceil = function(date) { + return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; + }; + + interval.round = function(date) { + var d0 = interval(date), + d1 = interval.ceil(date); + return date - d0 < d1 - date ? d0 : d1; + }; + + interval.offset = function(date, step) { + return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; + }; + + interval.range = function(start, stop, step) { + var range = []; + start = interval.ceil(start); + step = step == null ? 1 : Math.floor(step); + if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date + do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) + return range; + }; + + interval.filter = function(test) { + return newInterval(function(date) { + if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); + }, function(date, step) { + if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty + }); + }; + + if (count) { + interval.count = function(start, end) { + t0$1.setTime(+start), t1$1.setTime(+end); + floori(t0$1), floori(t1$1); + return Math.floor(count(t0$1, t1$1)); + }; + + interval.every = function(step) { + step = Math.floor(step); + return !isFinite(step) || !(step > 0) ? null + : !(step > 1) ? interval + : interval.filter(field + ? function(d) { return field(d) % step === 0; } + : function(d) { return interval.count(0, d) % step === 0; }); + }; + } + + return interval; +} + +var millisecond = newInterval(function() { + // noop +}, function(date, step) { + date.setTime(+date + step); +}, function(start, end) { + return end - start; +}); + +// An optimized implementation for this simple case. +millisecond.every = function(k) { + k = Math.floor(k); + if (!isFinite(k) || !(k > 0)) return null; + if (!(k > 1)) return millisecond; + return newInterval(function(date) { + date.setTime(Math.floor(date / k) * k); + }, function(date, step) { + date.setTime(+date + step * k); + }, function(start, end) { + return (end - start) / k; + }); +}; + +var milliseconds = millisecond.range; + +var durationSecond = 1e3; +var durationMinute = 6e4; +var durationHour = 36e5; +var durationDay = 864e5; +var durationWeek = 6048e5; + +var second = newInterval(function(date) { + date.setTime(Math.floor(date / durationSecond) * durationSecond); +}, function(date, step) { + date.setTime(+date + step * durationSecond); +}, function(start, end) { + return (end - start) / durationSecond; +}, function(date) { + return date.getUTCSeconds(); +}); + +var seconds = second.range; + +var minute = newInterval(function(date) { + date.setTime(Math.floor(date / durationMinute) * durationMinute); +}, function(date, step) { + date.setTime(+date + step * durationMinute); +}, function(start, end) { + return (end - start) / durationMinute; +}, function(date) { + return date.getMinutes(); +}); + +var minutes = minute.range; + +var hour = newInterval(function(date) { + var offset = date.getTimezoneOffset() * durationMinute % durationHour; + if (offset < 0) offset += durationHour; + date.setTime(Math.floor((+date - offset) / durationHour) * durationHour + offset); +}, function(date, step) { + date.setTime(+date + step * durationHour); +}, function(start, end) { + return (end - start) / durationHour; +}, function(date) { + return date.getHours(); +}); + +var hours = hour.range; + +var day = newInterval(function(date) { + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setDate(date.getDate() + step); +}, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay; +}, function(date) { + return date.getDate() - 1; +}); + +var days = day.range; + +function weekday(i) { + return newInterval(function(date) { + date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setDate(date.getDate() + step * 7); + }, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek; + }); +} + +var sunday = weekday(0); +var monday = weekday(1); +var tuesday = weekday(2); +var wednesday = weekday(3); +var thursday = weekday(4); +var friday = weekday(5); +var saturday = weekday(6); + +var sundays = sunday.range; +var mondays = monday.range; +var tuesdays = tuesday.range; +var wednesdays = wednesday.range; +var thursdays = thursday.range; +var fridays = friday.range; +var saturdays = saturday.range; + +var month = newInterval(function(date) { + date.setDate(1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setMonth(date.getMonth() + step); +}, function(start, end) { + return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; +}, function(date) { + return date.getMonth(); +}); + +var months = month.range; + +var year = newInterval(function(date) { + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setFullYear(date.getFullYear() + step); +}, function(start, end) { + return end.getFullYear() - start.getFullYear(); +}, function(date) { + return date.getFullYear(); +}); + +// An optimized implementation for this simple case. +year.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setFullYear(Math.floor(date.getFullYear() / k) * k); + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setFullYear(date.getFullYear() + step * k); + }); +}; + +var years = year.range; + +var utcMinute = newInterval(function(date) { + date.setUTCSeconds(0, 0); +}, function(date, step) { + date.setTime(+date + step * durationMinute); +}, function(start, end) { + return (end - start) / durationMinute; +}, function(date) { + return date.getUTCMinutes(); +}); + +var utcMinutes = utcMinute.range; + +var utcHour = newInterval(function(date) { + date.setUTCMinutes(0, 0, 0); +}, function(date, step) { + date.setTime(+date + step * durationHour); +}, function(start, end) { + return (end - start) / durationHour; +}, function(date) { + return date.getUTCHours(); +}); + +var utcHours = utcHour.range; + +var utcDay = newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCDate(date.getUTCDate() + step); +}, function(start, end) { + return (end - start) / durationDay; +}, function(date) { + return date.getUTCDate() - 1; +}); + +var utcDays = utcDay.range; + +function utcWeekday(i) { + return newInterval(function(date) { + date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCDate(date.getUTCDate() + step * 7); + }, function(start, end) { + return (end - start) / durationWeek; + }); +} + +var utcSunday = utcWeekday(0); +var utcMonday = utcWeekday(1); +var utcTuesday = utcWeekday(2); +var utcWednesday = utcWeekday(3); +var utcThursday = utcWeekday(4); +var utcFriday = utcWeekday(5); +var utcSaturday = utcWeekday(6); + +var utcSundays = utcSunday.range; +var utcMondays = utcMonday.range; +var utcTuesdays = utcTuesday.range; +var utcWednesdays = utcWednesday.range; +var utcThursdays = utcThursday.range; +var utcFridays = utcFriday.range; +var utcSaturdays = utcSaturday.range; + +var utcMonth = newInterval(function(date) { + date.setUTCDate(1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCMonth(date.getUTCMonth() + step); +}, function(start, end) { + return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; +}, function(date) { + return date.getUTCMonth(); +}); + +var utcMonths = utcMonth.range; + +var utcYear = newInterval(function(date) { + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step); +}, function(start, end) { + return end.getUTCFullYear() - start.getUTCFullYear(); +}, function(date) { + return date.getUTCFullYear(); +}); + +// An optimized implementation for this simple case. +utcYear.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step * k); + }); +}; + +var utcYears = utcYear.range; + +// Computes the decimal coefficient and exponent of the specified number x with +// significant digits p, where x is positive and p is in [1, 21] or undefined. +// For example, formatDecimal(1.23) returns ["123", 0]. +var formatDecimal = function(x, p) { + if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity + var i, coefficient = x.slice(0, i); + + // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ + // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x.slice(i + 1) + ]; +}; + +var exponent$1 = function(x) { + return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; +}; + +var formatGroup = function(grouping, thousands) { + return function(value, width) { + var i = value.length, + t = [], + j = 0, + g = 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 = grouping[j = (j + 1) % grouping.length]; + } + + return t.reverse().join(thousands); + }; +}; + +var formatDefault = function(x, p) { + x = x.toPrecision(p); + + out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { + switch (x[i]) { + case ".": i0 = i1 = i; break; + case "0": if (i0 === 0) i0 = i; i1 = i; break; + case "e": break out; + default: if (i0 > 0) i0 = 0; break; + } + } + + return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; +}; + +var prefixExponent; + +var formatPrefixAuto = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1], + i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, + n = coefficient.length; + return i === n ? coefficient + : i > n ? coefficient + new Array(i - n + 1).join("0") + : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) + : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! +}; + +var formatRounded = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1]; + return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient + : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) + : coefficient + new Array(exponent - coefficient.length + 2).join("0"); +}; + +var formatTypes = { + "": formatDefault, + "%": function(x, p) { return (x * 100).toFixed(p); }, + "b": function(x) { return Math.round(x).toString(2); }, + "c": function(x) { return x + ""; }, + "d": function(x) { return Math.round(x).toString(10); }, + "e": function(x, p) { return x.toExponential(p); }, + "f": function(x, p) { return x.toFixed(p); }, + "g": function(x, p) { return x.toPrecision(p); }, + "o": function(x) { return Math.round(x).toString(8); }, + "p": function(x, p) { return formatRounded(x * 100, p); }, + "r": formatRounded, + "s": formatPrefixAuto, + "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, + "x": function(x) { return Math.round(x).toString(16); } +}; + +// [[fill]align][sign][symbol][0][width][,][.precision][type] +var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; + +var formatSpecifier = function(specifier) { + return new FormatSpecifier(specifier); +}; + +function FormatSpecifier(specifier) { + if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); + + var match, + fill = match[1] || " ", + align = match[2] || ">", + sign = match[3] || "-", + symbol = match[4] || "", + zero = !!match[5], + width = match[6] && +match[6], + comma = !!match[7], + precision = match[8] && +match[8].slice(1), + type = match[9] || ""; + + // The "n" type is an alias for ",g". + if (type === "n") comma = true, type = "g"; + + // Map invalid types to the default format. + else if (!formatTypes[type]) type = ""; + + // If zero fill is specified, padding goes after sign and before digits. + if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; + + this.fill = fill; + this.align = align; + this.sign = sign; + this.symbol = symbol; + this.zero = zero; + this.width = width; + this.comma = comma; + this.precision = precision; + this.type = type; +} + +FormatSpecifier.prototype.toString = function() { + return this.fill + + this.align + + this.sign + + this.symbol + + (this.zero ? "0" : "") + + (this.width == null ? "" : Math.max(1, this.width | 0)) + + (this.comma ? "," : "") + + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) + + this.type; +}; + +var prefixes = ["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"]; + +function identity$3(x) { + return x; +} + +var formatLocale = function(locale) { + var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3, + currency = locale.currency, + decimal = locale.decimal; + + function newFormat(specifier) { + specifier = formatSpecifier(specifier); + + var fill = specifier.fill, + align = specifier.align, + sign = specifier.sign, + symbol = specifier.symbol, + zero = specifier.zero, + width = specifier.width, + comma = specifier.comma, + precision = specifier.precision, + type = specifier.type; + + // Compute the prefix and suffix. + // For SI-prefix, the suffix is lazily computed. + var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", + suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : ""; + + // What format function should we use? + // Is this an integer type? + // Can this type generate exponential notation? + var formatType = formatTypes[type], + maybeSuffix = !type || /[defgprs%]/.test(type); + + // Set the default precision if not specified, + // or clamp the specified precision to the supported range. + // For significant precision, it must be in [1, 21]. + // For fixed precision, it must be in [0, 20]. + precision = precision == null ? (type ? 6 : 12) + : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) + : Math.max(0, Math.min(20, precision)); + + function format(value) { + var valuePrefix = prefix, + valueSuffix = suffix, + i, n, c; + + if (type === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; + + // Convert negative to positive, and compute the prefix. + // Note that -0 is not less than 0, but 1 / -0 is! + var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true); + + // Perform the initial formatting. + value = formatType(value, precision); + + // If the original value was negative, it may be rounded to zero during + // formatting; treat this as (positive) zero. + if (valueNegative) { + i = -1, n = value.length; + valueNegative = false; + while (++i < n) { + if (c = value.charCodeAt(i), (48 < c && c < 58) + || (type === "x" && 96 < c && c < 103) + || (type === "X" && 64 < c && c < 71)) { + valueNegative = true; + break; + } + } + } + + // Compute the prefix and suffix. + valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); + + // Break the formatted value into the integer “value” part that can be + // grouped, and fractional or exponential “suffix” part that is not. + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c = value.charCodeAt(i), 48 > c || c > 57) { + valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } + } + + // If the fill character is not "0", grouping is applied before padding. + if (comma && !zero) value = group(value, Infinity); + + // Compute the padding. + var length = valuePrefix.length + value.length + valueSuffix.length, + padding = length < width ? new Array(width - length + 1).join(fill) : ""; + + // If the fill character is "0", grouping is applied after padding. + if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; + + // Reconstruct the final output based on the desired alignment. + switch (align) { + case "<": return valuePrefix + value + valueSuffix + padding; + case "=": return valuePrefix + padding + value + valueSuffix; + case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); + } + return padding + valuePrefix + value + valueSuffix; + } + + format.toString = function() { + return specifier + ""; + }; + + return format; + } + + function formatPrefix(specifier, value) { + var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), + e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3, + k = Math.pow(10, -e), + prefix = prefixes[8 + e / 3]; + return function(value) { + return f(k * value) + prefix; + }; + } + + return { + format: newFormat, + formatPrefix: formatPrefix + }; +}; + +var locale$1; + + + +defaultLocale({ + decimal: ".", + thousands: ",", + grouping: [3], + currency: ["$", ""] +}); + +function defaultLocale(definition) { + locale$1 = formatLocale(definition); + exports.format = locale$1.format; + exports.formatPrefix = locale$1.formatPrefix; + return locale$1; +} + +var precisionFixed = function(step) { + return Math.max(0, -exponent$1(Math.abs(step))); +}; + +var precisionPrefix = function(step, value) { + return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step))); +}; + +var precisionRound = function(step, max) { + step = Math.abs(step), max = Math.abs(max) - step; + return Math.max(0, exponent$1(max) - exponent$1(step)) + 1; +}; + +function localDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); + date.setFullYear(d.y); + return date; + } + return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); +} + +function utcDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); + date.setUTCFullYear(d.y); + return date; + } + return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); +} + +function newYear(y) { + return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; +} + +function formatLocale$1(locale) { + var locale_dateTime = locale.dateTime, + locale_date = locale.date, + locale_time = locale.time, + locale_periods = locale.periods, + locale_weekdays = locale.days, + locale_shortWeekdays = locale.shortDays, + locale_months = locale.months, + locale_shortMonths = locale.shortMonths; + + var periodRe = formatRe(locale_periods), + periodLookup = formatLookup(locale_periods), + weekdayRe = formatRe(locale_weekdays), + weekdayLookup = formatLookup(locale_weekdays), + shortWeekdayRe = formatRe(locale_shortWeekdays), + shortWeekdayLookup = formatLookup(locale_shortWeekdays), + monthRe = formatRe(locale_months), + monthLookup = formatLookup(locale_months), + shortMonthRe = formatRe(locale_shortMonths), + shortMonthLookup = formatLookup(locale_shortMonths); + + var formats = { + "a": formatShortWeekday, + "A": formatWeekday, + "b": formatShortMonth, + "B": formatMonth, + "c": null, + "d": formatDayOfMonth, + "e": formatDayOfMonth, + "H": formatHour24, + "I": formatHour12, + "j": formatDayOfYear, + "L": formatMilliseconds, + "m": formatMonthNumber, + "M": formatMinutes, + "p": formatPeriod, + "S": formatSeconds, + "U": formatWeekNumberSunday, + "w": formatWeekdayNumber, + "W": formatWeekNumberMonday, + "x": null, + "X": null, + "y": formatYear, + "Y": formatFullYear, + "Z": formatZone, + "%": formatLiteralPercent + }; + + var utcFormats = { + "a": formatUTCShortWeekday, + "A": formatUTCWeekday, + "b": formatUTCShortMonth, + "B": formatUTCMonth, + "c": null, + "d": formatUTCDayOfMonth, + "e": formatUTCDayOfMonth, + "H": formatUTCHour24, + "I": formatUTCHour12, + "j": formatUTCDayOfYear, + "L": formatUTCMilliseconds, + "m": formatUTCMonthNumber, + "M": formatUTCMinutes, + "p": formatUTCPeriod, + "S": formatUTCSeconds, + "U": formatUTCWeekNumberSunday, + "w": formatUTCWeekdayNumber, + "W": formatUTCWeekNumberMonday, + "x": null, + "X": null, + "y": formatUTCYear, + "Y": formatUTCFullYear, + "Z": formatUTCZone, + "%": formatLiteralPercent + }; + + var parses = { + "a": parseShortWeekday, + "A": parseWeekday, + "b": parseShortMonth, + "B": parseMonth, + "c": parseLocaleDateTime, + "d": parseDayOfMonth, + "e": parseDayOfMonth, + "H": parseHour24, + "I": parseHour24, + "j": parseDayOfYear, + "L": parseMilliseconds, + "m": parseMonthNumber, + "M": parseMinutes, + "p": parsePeriod, + "S": parseSeconds, + "U": parseWeekNumberSunday, + "w": parseWeekdayNumber, + "W": parseWeekNumberMonday, + "x": parseLocaleDate, + "X": parseLocaleTime, + "y": parseYear, + "Y": parseFullYear, + "Z": parseZone, + "%": parseLiteralPercent + }; + + // These recursive directive definitions must be deferred. + formats.x = newFormat(locale_date, formats); + formats.X = newFormat(locale_time, formats); + formats.c = newFormat(locale_dateTime, formats); + utcFormats.x = newFormat(locale_date, utcFormats); + utcFormats.X = newFormat(locale_time, utcFormats); + utcFormats.c = newFormat(locale_dateTime, utcFormats); + + function newFormat(specifier, formats) { + return function(date) { + var string = [], + i = -1, + j = 0, + n = specifier.length, + c, + pad, + format; + + if (!(date instanceof Date)) date = new Date(+date); + + while (++i < n) { + if (specifier.charCodeAt(i) === 37) { + string.push(specifier.slice(j, i)); + if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); + else pad = c === "e" ? " " : "0"; + if (format = formats[c]) c = format(date, pad); + string.push(c); + j = i + 1; + } + } + + string.push(specifier.slice(j, i)); + return string.join(""); + }; + } + + function newParse(specifier, newDate) { + return function(string) { + var d = newYear(1900), + i = parseSpecifier(d, specifier, string += "", 0); + if (i != string.length) return null; + + // The am-pm flag is 0 for AM, and 1 for PM. + if ("p" in d) d.H = d.H % 12 + d.p * 12; + + // Convert day-of-week and week-of-year to day-of-year. + if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "W" in d ? 1 : 0; + var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); + d.m = 0; + d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$$1 + 5) % 7 : d.w + d.U * 7 - (day$$1 + 6) % 7; + } + + // If a time zone is specified, all fields are interpreted as UTC and then + // offset according to the specified time zone. + if ("Z" in d) { + d.H += d.Z / 100 | 0; + d.M += d.Z % 100; + return utcDate(d); + } + + // Otherwise, all fields are in local time. + return newDate(d); + }; + } + + function parseSpecifier(d, specifier, string, j) { + var i = 0, + n = specifier.length, + m = string.length, + c, + parse; + + while (i < n) { + if (j >= m) return -1; + c = specifier.charCodeAt(i++); + if (c === 37) { + c = specifier.charAt(i++); + parse = parses[c in pads ? specifier.charAt(i++) : c]; + if (!parse || ((j = parse(d, string, j)) < 0)) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + + return j; + } + + function parsePeriod(d, string, i) { + var n = periodRe.exec(string.slice(i)); + return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortWeekday(d, string, i) { + var n = shortWeekdayRe.exec(string.slice(i)); + return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseWeekday(d, string, i) { + var n = weekdayRe.exec(string.slice(i)); + return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortMonth(d, string, i) { + var n = shortMonthRe.exec(string.slice(i)); + return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseMonth(d, string, i) { + var n = monthRe.exec(string.slice(i)); + return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseLocaleDateTime(d, string, i) { + return parseSpecifier(d, locale_dateTime, string, i); + } + + function parseLocaleDate(d, string, i) { + return parseSpecifier(d, locale_date, string, i); + } + + function parseLocaleTime(d, string, i) { + return parseSpecifier(d, locale_time, string, i); + } + + function formatShortWeekday(d) { + return locale_shortWeekdays[d.getDay()]; + } + + function formatWeekday(d) { + return locale_weekdays[d.getDay()]; + } + + function formatShortMonth(d) { + return locale_shortMonths[d.getMonth()]; + } + + function formatMonth(d) { + return locale_months[d.getMonth()]; + } + + function formatPeriod(d) { + return locale_periods[+(d.getHours() >= 12)]; + } + + function formatUTCShortWeekday(d) { + return locale_shortWeekdays[d.getUTCDay()]; + } + + function formatUTCWeekday(d) { + return locale_weekdays[d.getUTCDay()]; + } + + function formatUTCShortMonth(d) { + return locale_shortMonths[d.getUTCMonth()]; + } + + function formatUTCMonth(d) { + return locale_months[d.getUTCMonth()]; + } + + function formatUTCPeriod(d) { + return locale_periods[+(d.getUTCHours() >= 12)]; + } + + return { + format: function(specifier) { + var f = newFormat(specifier += "", formats); + f.toString = function() { return specifier; }; + return f; + }, + parse: function(specifier) { + var p = newParse(specifier += "", localDate); + p.toString = function() { return specifier; }; + return p; + }, + utcFormat: function(specifier) { + var f = newFormat(specifier += "", utcFormats); + f.toString = function() { return specifier; }; + return f; + }, + utcParse: function(specifier) { + var p = newParse(specifier, utcDate); + p.toString = function() { return specifier; }; + return p; + } + }; +} + +var pads = {"-": "", "_": " ", "0": "0"}; +var numberRe = /^\s*\d+/; +var percentRe = /^%/; +var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + +function pad(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 requote(s) { + return s.replace(requoteRe, "\\$&"); +} + +function formatRe(names) { + return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); +} + +function formatLookup(names) { + var map = {}, i = -1, n = names.length; + while (++i < n) map[names[i].toLowerCase()] = i; + return map; +} + +function parseWeekdayNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.w = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.U = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.W = +n[0], i + n[0].length) : -1; +} + +function parseFullYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 4)); + return n ? (d.y = +n[0], i + n[0].length) : -1; +} + +function parseYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; +} + +function parseZone(d, string, i) { + var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6)); + return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; +} + +function parseMonthNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.m = n[0] - 1, i + n[0].length) : -1; +} + +function parseDayOfMonth(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.d = +n[0], i + n[0].length) : -1; +} + +function parseDayOfYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; +} + +function parseHour24(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.H = +n[0], i + n[0].length) : -1; +} + +function parseMinutes(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.M = +n[0], i + n[0].length) : -1; +} + +function parseSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.S = +n[0], i + n[0].length) : -1; +} + +function parseMilliseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.L = +n[0], i + n[0].length) : -1; +} + +function parseLiteralPercent(d, string, i) { + var n = percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; +} + +function formatDayOfMonth(d, p) { + return pad(d.getDate(), p, 2); +} + +function formatHour24(d, p) { + return pad(d.getHours(), p, 2); +} + +function formatHour12(d, p) { + return pad(d.getHours() % 12 || 12, p, 2); +} + +function formatDayOfYear(d, p) { + return pad(1 + day.count(year(d), d), p, 3); +} + +function formatMilliseconds(d, p) { + return pad(d.getMilliseconds(), p, 3); +} + +function formatMonthNumber(d, p) { + return pad(d.getMonth() + 1, p, 2); +} + +function formatMinutes(d, p) { + return pad(d.getMinutes(), p, 2); +} + +function formatSeconds(d, p) { + return pad(d.getSeconds(), p, 2); +} + +function formatWeekNumberSunday(d, p) { + return pad(sunday.count(year(d), d), p, 2); +} + +function formatWeekdayNumber(d) { + return d.getDay(); +} + +function formatWeekNumberMonday(d, p) { + return pad(monday.count(year(d), d), p, 2); +} + +function formatYear(d, p) { + return pad(d.getFullYear() % 100, p, 2); +} + +function formatFullYear(d, p) { + return pad(d.getFullYear() % 10000, p, 4); +} + +function formatZone(d) { + var z = d.getTimezoneOffset(); + return (z > 0 ? "-" : (z *= -1, "+")) + + pad(z / 60 | 0, "0", 2) + + pad(z % 60, "0", 2); +} + +function formatUTCDayOfMonth(d, p) { + return pad(d.getUTCDate(), p, 2); +} + +function formatUTCHour24(d, p) { + return pad(d.getUTCHours(), p, 2); +} + +function formatUTCHour12(d, p) { + return pad(d.getUTCHours() % 12 || 12, p, 2); +} + +function formatUTCDayOfYear(d, p) { + return pad(1 + utcDay.count(utcYear(d), d), p, 3); +} + +function formatUTCMilliseconds(d, p) { + return pad(d.getUTCMilliseconds(), p, 3); +} + +function formatUTCMonthNumber(d, p) { + return pad(d.getUTCMonth() + 1, p, 2); +} + +function formatUTCMinutes(d, p) { + return pad(d.getUTCMinutes(), p, 2); +} + +function formatUTCSeconds(d, p) { + return pad(d.getUTCSeconds(), p, 2); +} + +function formatUTCWeekNumberSunday(d, p) { + return pad(utcSunday.count(utcYear(d), d), p, 2); +} + +function formatUTCWeekdayNumber(d) { + return d.getUTCDay(); +} + +function formatUTCWeekNumberMonday(d, p) { + return pad(utcMonday.count(utcYear(d), d), p, 2); +} + +function formatUTCYear(d, p) { + return pad(d.getUTCFullYear() % 100, p, 2); +} + +function formatUTCFullYear(d, p) { + return pad(d.getUTCFullYear() % 10000, p, 4); +} + +function formatUTCZone() { + return "+0000"; +} + +function formatLiteralPercent() { + return "%"; +} + +var locale$2; + + + + + +defaultLocale$1({ + dateTime: "%x, %X", + date: "%-m/%-d/%Y", + time: "%-I:%M:%S %p", + 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"] +}); + +function defaultLocale$1(definition) { + locale$2 = formatLocale$1(definition); + exports.timeFormat = locale$2.format; + exports.timeParse = locale$2.parse; + exports.utcFormat = locale$2.utcFormat; + exports.utcParse = locale$2.utcParse; + return locale$2; +} + +var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; + +function formatIsoNative(date) { + return date.toISOString(); +} + +var formatIso = Date.prototype.toISOString + ? formatIsoNative + : exports.utcFormat(isoSpecifier); + +function parseIsoNative(string) { + var date = new Date(string); + return isNaN(date) ? null : date; +} + +var parseIso = +new Date("2000-01-01T00:00:00.000Z") + ? parseIsoNative + : exports.utcParse(isoSpecifier); + +var array$2 = Array.prototype; + +var map$3 = array$2.map; +var slice$3 = array$2.slice; + +var implicit = {name: "implicit"}; + +function ordinal(range) { + var index = map$1(), + domain = [], + unknown = implicit; + + range = range == null ? [] : slice$3.call(range); + + function scale(d) { + var key = d + "", i = index.get(key); + if (!i) { + if (unknown !== implicit) return unknown; + index.set(key, i = domain.push(d)); + } + return range[(i - 1) % range.length]; + } + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = [], index = map$1(); + var i = -1, n = _.length, d, key; + while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); + return scale; + }; + + scale.range = function(_) { + return arguments.length ? (range = slice$3.call(_), scale) : range.slice(); + }; + + scale.unknown = function(_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function() { + return ordinal() + .domain(domain) + .range(range) + .unknown(unknown); + }; + + return scale; +} + +function band() { + var scale = ordinal().unknown(undefined), + domain = scale.domain, + ordinalRange = scale.range, + range$$1 = [0, 1], + step, + bandwidth, + round = false, + paddingInner = 0, + paddingOuter = 0, + align = 0.5; + + delete scale.unknown; + + function rescale() { + var n = domain().length, + reverse = range$$1[1] < range$$1[0], + start = range$$1[reverse - 0], + stop = range$$1[1 - reverse]; + step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); + if (round) step = Math.floor(step); + start += (stop - start - step * (n - paddingInner)) * align; + bandwidth = step * (1 - paddingInner); + if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); + var values = range(n).map(function(i) { return start + step * i; }); + return ordinalRange(reverse ? values.reverse() : values); + } + + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice(); + }; + + scale.rangeRound = function(_) { + return range$$1 = [+_[0], +_[1]], round = true, rescale(); + }; + + scale.bandwidth = function() { + return bandwidth; + }; + + scale.step = function() { + return step; + }; + + scale.round = function(_) { + return arguments.length ? (round = !!_, rescale()) : round; + }; + + scale.padding = function(_) { + return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; + + scale.paddingInner = function(_) { + return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; + + scale.paddingOuter = function(_) { + return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter; + }; + + scale.align = function(_) { + return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; + }; + + scale.copy = function() { + return band() + .domain(domain()) + .range(range$$1) + .round(round) + .paddingInner(paddingInner) + .paddingOuter(paddingOuter) + .align(align); + }; + + return rescale(); +} + +function pointish(scale) { + var copy = scale.copy; + + scale.padding = scale.paddingOuter; + delete scale.paddingInner; + delete scale.paddingOuter; + + scale.copy = function() { + return pointish(copy()); + }; + + return scale; +} + +function point$4() { + return pointish(band().paddingInner(1)); +} + +var constant$4 = function(x) { + return function() { + return x; + }; +}; + +var number$1 = function(x) { + return +x; +}; + +var unit = [0, 1]; + +function deinterpolateLinear(a, b) { + return (b -= (a = +a)) + ? function(x) { return (x - a) / b; } + : constant$4(b); +} + +function deinterpolateClamp(deinterpolate) { + return function(a, b) { + var d = deinterpolate(a = +a, b = +b); + return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; + }; +} + +function reinterpolateClamp(reinterpolate) { + return function(a, b) { + var r = reinterpolate(a = +a, b = +b); + return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; + }; +} + +function bimap(domain, range$$1, deinterpolate, reinterpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1]; + if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); + else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); + return function(x) { return r0(d0(x)); }; +} + +function polymap(domain, range$$1, deinterpolate, reinterpolate) { + var j = Math.min(domain.length, range$$1.length) - 1, + d = new Array(j), + r = new Array(j), + i = -1; + + // Reverse descending domains. + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range$$1 = range$$1.slice().reverse(); + } + + while (++i < j) { + d[i] = deinterpolate(domain[i], domain[i + 1]); + r[i] = reinterpolate(range$$1[i], range$$1[i + 1]); + } + + return function(x) { + var i = bisectRight(domain, x, 1, j) - 1; + return r[i](d[i](x)); + }; +} + +function copy(source, target) { + return target + .domain(source.domain()) + .range(source.range()) + .interpolate(source.interpolate()) + .clamp(source.clamp()); +} + +// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. +// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. +function continuous(deinterpolate, reinterpolate) { + var domain = unit, + range$$1 = unit, + interpolate$$1 = interpolate, + clamp = false, + piecewise, + output, + input; + + function rescale() { + piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap; + output = input = null; + return scale; + } + + function scale(x) { + return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); + } + + scale.invert = function(y) { + return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); + }; + + scale.domain = function(_) { + return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice(); + }; + + scale.rangeRound = function(_) { + return range$$1 = slice$3.call(_), interpolate$$1 = interpolateRound, rescale(); + }; + + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, rescale()) : clamp; + }; + + scale.interpolate = function(_) { + return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; + }; + + return rescale(); +} + +var tickFormat = function(domain, count, specifier) { + var start = domain[0], + stop = domain[domain.length - 1], + step = tickStep(start, stop, count == null ? 10 : count), + precision; + specifier = formatSpecifier(specifier == null ? ",f" : specifier); + switch (specifier.type) { + case "s": { + var value = Math.max(Math.abs(start), Math.abs(stop)); + if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision; + return exports.formatPrefix(specifier, value); + } + case "": + case "e": + case "g": + case "p": + case "r": { + if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); + break; + } + case "f": + case "%": { + if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; + break; + } + } + return exports.format(specifier); +}; + +function linearish(scale) { + var domain = scale.domain; + + scale.ticks = function(count) { + var d = domain(); + return ticks(d[0], d[d.length - 1], count == null ? 10 : count); + }; + + scale.tickFormat = function(count, specifier) { + return tickFormat(domain(), count, specifier); + }; + + scale.nice = function(count) { + var d = domain(), + i = d.length - 1, + n = count == null ? 10 : count, + start = d[0], + stop = d[i], + step = tickStep(start, stop, n); + + if (step) { + step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n); + d[0] = Math.floor(start / step) * step; + d[i] = Math.ceil(stop / step) * step; + domain(d); + } + + return scale; + }; + + return scale; +} + +function linear$2() { + var scale = continuous(deinterpolateLinear, interpolateNumber); + + scale.copy = function() { + return copy(scale, linear$2()); + }; + + return linearish(scale); +} + +function identity$4() { + var domain = [0, 1]; + + function scale(x) { + return +x; + } + + scale.invert = scale; + + scale.domain = scale.range = function(_) { + return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice(); + }; + + scale.copy = function() { + return identity$4().domain(domain); + }; + + return linearish(scale); +} + +var nice = function(domain, interval) { + domain = domain.slice(); + + var i0 = 0, + i1 = domain.length - 1, + x0 = domain[i0], + x1 = domain[i1], + t; + + if (x1 < x0) { + t = i0, i0 = i1, i1 = t; + t = x0, x0 = x1, x1 = t; + } + + domain[i0] = interval.floor(x0); + domain[i1] = interval.ceil(x1); + return domain; +}; + +function deinterpolate(a, b) { + return (b = Math.log(b / a)) + ? function(x) { return Math.log(x / a) / b; } + : constant$4(b); +} + +function reinterpolate(a, b) { + return a < 0 + ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); } + : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); }; +} + +function pow10(x) { + return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; +} + +function powp(base) { + return base === 10 ? pow10 + : base === Math.E ? Math.exp + : function(x) { return Math.pow(base, x); }; +} + +function logp(base) { + return base === Math.E ? Math.log + : base === 10 && Math.log10 + || base === 2 && Math.log2 + || (base = Math.log(base), function(x) { return Math.log(x) / base; }); +} + +function reflect(f) { + return function(x) { + return -f(-x); + }; +} + +function log() { + var scale = continuous(deinterpolate, reinterpolate).domain([1, 10]), + domain = scale.domain, + base = 10, + logs = logp(10), + pows = powp(10); + + function rescale() { + logs = logp(base), pows = powp(base); + if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows); + return scale; + } + + scale.base = function(_) { + return arguments.length ? (base = +_, rescale()) : base; + }; + + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.ticks = function(count) { + var d = domain(), + u = d[0], + v = d[d.length - 1], + r; + + if (r = v < u) i = u, u = v, v = i; + + var i = logs(u), + j = logs(v), + p, + k, + t, + n = count == null ? 10 : +count, + z = []; + + if (!(base % 1) && j - i < n) { + i = Math.round(i) - 1, j = Math.round(j) + 1; + if (u > 0) for (; i < j; ++i) { + for (k = 1, p = pows(i); k < base; ++k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); + } + } else for (; i < j; ++i) { + for (k = base - 1, p = pows(i); k >= 1; --k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); + } + } + } else { + z = ticks(i, j, Math.min(j - i, n)).map(pows); + } + + return r ? z.reverse() : z; + }; + + scale.tickFormat = function(count, specifier) { + if (specifier == null) specifier = base === 10 ? ".0e" : ","; + if (typeof specifier !== "function") specifier = exports.format(specifier); + if (count === Infinity) return specifier; + if (count == null) count = 10; + var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? + return function(d) { + var i = d / pows(Math.round(logs(d))); + if (i * base < base - 0.5) i *= base; + return i <= k ? specifier(d) : ""; + }; + }; + + scale.nice = function() { + return domain(nice(domain(), { + floor: function(x) { return pows(Math.floor(logs(x))); }, + ceil: function(x) { return pows(Math.ceil(logs(x))); } + })); + }; + + scale.copy = function() { + return copy(scale, log().base(base)); + }; + + return scale; +} + +function raise(x, exponent) { + return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); +} + +function pow() { + var exponent = 1, + scale = continuous(deinterpolate, reinterpolate), + domain = scale.domain; + + function deinterpolate(a, b) { + return (b = raise(b, exponent) - (a = raise(a, exponent))) + ? function(x) { return (raise(x, exponent) - a) / b; } + : constant$4(b); + } + + function reinterpolate(a, b) { + b = raise(b, exponent) - (a = raise(a, exponent)); + return function(t) { return raise(a + b * t, 1 / exponent); }; + } + + scale.exponent = function(_) { + return arguments.length ? (exponent = +_, domain(domain())) : exponent; + }; + + scale.copy = function() { + return copy(scale, pow().exponent(exponent)); + }; + + return linearish(scale); +} + +function sqrt() { + return pow().exponent(0.5); +} + +function quantile$$1() { + var domain = [], + range$$1 = [], + thresholds = []; + + function rescale() { + var i = 0, n = Math.max(1, range$$1.length); + thresholds = new Array(n - 1); + while (++i < n) thresholds[i - 1] = threshold(domain, i / n); + return scale; + } + + function scale(x) { + if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)]; + } + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] : [ + i > 0 ? thresholds[i - 1] : domain[0], + i < thresholds.length ? thresholds[i] : domain[domain.length - 1] + ]; + }; + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = []; + for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d); + domain.sort(ascending); + return rescale(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice(); + }; + + scale.quantiles = function() { + return thresholds.slice(); + }; + + scale.copy = function() { + return quantile$$1() + .domain(domain) + .range(range$$1); + }; + + return scale; +} + +function quantize$1() { + var x0 = 0, + x1 = 1, + n = 1, + domain = [0.5], + range$$1 = [0, 1]; + + function scale(x) { + if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; + } + + function rescale() { + var i = -1; + domain = new Array(n); + while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); + return scale; + } + + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; + }; + + scale.range = function(_) { + return arguments.length ? (n = (range$$1 = slice$3.call(_)).length - 1, rescale()) : range$$1.slice(); + }; + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] + : i < 1 ? [x0, domain[0]] + : i >= n ? [domain[n - 1], x1] + : [domain[i - 1], domain[i]]; + }; + + scale.copy = function() { + return quantize$1() + .domain([x0, x1]) + .range(range$$1); + }; + + return linearish(scale); +} + +function threshold$1() { + var domain = [0.5], + range$$1 = [0, 1], + n = 1; + + function scale(x) { + if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; + } + + scale.domain = function(_) { + return arguments.length ? (domain = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice(); + }; + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return [domain[i - 1], domain[i]]; + }; + + scale.copy = function() { + return threshold$1() + .domain(domain) + .range(range$$1); + }; + + return scale; +} + +var durationSecond$1 = 1000; +var durationMinute$1 = durationSecond$1 * 60; +var durationHour$1 = durationMinute$1 * 60; +var durationDay$1 = durationHour$1 * 24; +var durationWeek$1 = durationDay$1 * 7; +var durationMonth = durationDay$1 * 30; +var durationYear = durationDay$1 * 365; + +function date$1(t) { + return new Date(t); +} + +function number$2(t) { + return t instanceof Date ? +t : +new Date(+t); +} + +function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) { + var scale = continuous(deinterpolateLinear, interpolateNumber), + invert = scale.invert, + domain = scale.domain; + + var formatMillisecond = format(".%L"), + formatSecond = format(":%S"), + formatMinute = format("%I:%M"), + formatHour = format("%I %p"), + formatDay = format("%a %d"), + formatWeek = format("%b %d"), + formatMonth = format("%B"), + formatYear = format("%Y"); + + var tickIntervals = [ + [second$$1, 1, durationSecond$1], + [second$$1, 5, 5 * durationSecond$1], + [second$$1, 15, 15 * durationSecond$1], + [second$$1, 30, 30 * durationSecond$1], + [minute$$1, 1, durationMinute$1], + [minute$$1, 5, 5 * durationMinute$1], + [minute$$1, 15, 15 * durationMinute$1], + [minute$$1, 30, 30 * durationMinute$1], + [ hour$$1, 1, durationHour$1 ], + [ hour$$1, 3, 3 * durationHour$1 ], + [ hour$$1, 6, 6 * durationHour$1 ], + [ hour$$1, 12, 12 * durationHour$1 ], + [ day$$1, 1, durationDay$1 ], + [ day$$1, 2, 2 * durationDay$1 ], + [ week, 1, durationWeek$1 ], + [ month$$1, 1, durationMonth ], + [ month$$1, 3, 3 * durationMonth ], + [ year$$1, 1, durationYear ] + ]; + + function tickFormat(date) { + return (second$$1(date) < date ? formatMillisecond + : minute$$1(date) < date ? formatSecond + : hour$$1(date) < date ? formatMinute + : day$$1(date) < date ? formatHour + : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek) + : year$$1(date) < date ? formatMonth + : formatYear)(date); + } + + function tickInterval(interval, start, stop, step) { + if (interval == null) interval = 10; + + // If a desired tick count is specified, pick a reasonable tick interval + // based on the extent of the domain and a rough estimate of tick size. + // Otherwise, assume interval is already a time interval and use it. + if (typeof interval === "number") { + var target = Math.abs(stop - start) / interval, + i = bisector(function(i) { return i[2]; }).right(tickIntervals, target); + if (i === tickIntervals.length) { + step = tickStep(start / durationYear, stop / durationYear, interval); + interval = year$$1; + } else if (i) { + i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; + step = i[1]; + interval = i[0]; + } else { + step = tickStep(start, stop, interval); + interval = millisecond$$1; + } + } + + return step == null ? interval : interval.every(step); + } + + scale.invert = function(y) { + return new Date(invert(y)); + }; + + scale.domain = function(_) { + return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1); + }; + + scale.ticks = function(interval, step) { + var d = domain(), + t0 = d[0], + t1 = d[d.length - 1], + r = t1 < t0, + t; + if (r) t = t0, t0 = t1, t1 = t; + t = tickInterval(interval, t0, t1, step); + t = t ? t.range(t0, t1 + 1) : []; // inclusive stop + return r ? t.reverse() : t; + }; + + scale.tickFormat = function(count, specifier) { + return specifier == null ? tickFormat : format(specifier); + }; + + scale.nice = function(interval, step) { + var d = domain(); + return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) + ? domain(nice(d, interval)) + : scale; + }; + + scale.copy = function() { + return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format)); + }; + + return scale; +} + +var time = function() { + return calendar(year, month, sunday, day, hour, minute, second, millisecond, exports.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); +}; + +var utcTime = function() { + return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, exports.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]); +}; + +var colors = function(s) { + return s.match(/.{6}/g).map(function(x) { + return "#" + x; + }); +}; + +var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); + +var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); + +var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); + +var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); + +var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0)); + +var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); + +var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); + +var rainbow = cubehelix(); + +var rainbow$1 = function(t) { + if (t < 0 || t > 1) t -= Math.floor(t); + var ts = Math.abs(t - 0.5); + rainbow.h = 360 * t - 100; + rainbow.s = 1.5 - 1.5 * ts; + rainbow.l = 0.8 - 0.9 * ts; + return rainbow + ""; +}; + +function ramp(range) { + var n = range.length; + return function(t) { + return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + }; +} + +var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); + +var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); + +var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); + +var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); + +function sequential(interpolator) { + var x0 = 0, + x1 = 1, + clamp = false; + + function scale(x) { + var t = (x - x0) / (x1 - x0); + return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t); + } + + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1]; + }; + + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, scale) : clamp; + }; + + scale.interpolator = function(_) { + return arguments.length ? (interpolator = _, scale) : interpolator; + }; + + scale.copy = function() { + return sequential(interpolator).domain([x0, x1]).clamp(clamp); + }; + + return linearish(scale); +} + +var xhtml = "http://www.w3.org/1999/xhtml"; + +var namespaces = { + svg: "http://www.w3.org/2000/svg", + xhtml: xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" +}; + +var namespace = function(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; +}; + +function creatorInherit(name) { + return function() { + var document = this.ownerDocument, + uri = this.namespaceURI; + return uri === xhtml && document.documentElement.namespaceURI === xhtml + ? document.createElement(name) + : document.createElementNS(uri, name); + }; +} + +function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; +} + +var creator = function(name) { + var fullname = namespace(name); + return (fullname.local + ? creatorFixed + : creatorInherit)(fullname); +}; + +var nextId = 0; + +function local() { + return new Local; +} + +function Local() { + this._ = "@" + (++nextId).toString(36); +} + +Local.prototype = local.prototype = { + constructor: Local, + get: function(node) { + var id = this._; + while (!(id in node)) if (!(node = node.parentNode)) return; + return node[id]; + }, + set: function(node, value) { + return node[this._] = value; + }, + remove: function(node) { + return this._ in node && delete node[this._]; + }, + toString: function() { + return this._; + } +}; + +var matcher = function(selector) { + return function() { + return this.matches(selector); + }; +}; + +if (typeof document !== "undefined") { + var element = document.documentElement; + if (!element.matches) { + var vendorMatches = element.webkitMatchesSelector + || element.msMatchesSelector + || element.mozMatchesSelector + || element.oMatchesSelector; + matcher = function(selector) { + return function() { + return vendorMatches.call(this, selector); + }; + }; + } +} + +var matcher$1 = matcher; + +var filterEvents = {}; + +exports.event = null; + +if (typeof document !== "undefined") { + var element$1 = document.documentElement; + if (!("onmouseenter" in element$1)) { + filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; + } +} + +function filterContextListener(listener, index, group) { + listener = contextListener(listener, index, group); + return function(event) { + var related = event.relatedTarget; + if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { + listener.call(this, event); + } + }; +} + +function contextListener(listener, index, group) { + return function(event1) { + var event0 = exports.event; // Events can be reentrant (e.g., focus). + exports.event = event1; + try { + listener.call(this, this.__data__, index, group); + } finally { + exports.event = event0; + } + }; +} + +function parseTypenames$1(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + return {type: t, name: name}; + }); +} + +function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) return; + for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + } else { + on[++i] = o; + } + } + if (++i) on.length = i; + else delete this.__on; + }; +} + +function onAdd(typename, value, capture) { + var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; + return function(d, i, group) { + var on = this.__on, o, listener = wrap(value, i, group); + if (on) for (var j = 0, m = on.length; j < m; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + this.addEventListener(o.type, o.listener = listener, o.capture = capture); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, capture); + o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; + if (!on) this.__on = [o]; + else on.push(o); + }; +} + +var selection_on = function(typename, value, capture) { + var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; + + if (arguments.length < 2) { + var on = this.node().__on; + if (on) for (var j = 0, m = on.length, o; j < m; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + + on = value ? onAdd : onRemove; + if (capture == null) capture = false; + for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); + return this; +}; + +function customEvent(event1, listener, that, args) { + var event0 = exports.event; + event1.sourceEvent = exports.event; + exports.event = event1; + try { + return listener.apply(that, args); + } finally { + exports.event = event0; + } +} + +var sourceEvent = function() { + var current = exports.event, source; + while (source = current.sourceEvent) current = source; + return current; +}; + +var point$5 = function(node, event) { + var svg = node.ownerSVGElement || node; + + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; + } + + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; +}; + +var mouse = function(node) { + var event = sourceEvent(); + if (event.changedTouches) event = event.changedTouches[0]; + return point$5(node, event); +}; + +function none$2() {} + +var selector = function(selector) { + return selector == null ? none$2 : function() { + return this.querySelector(selector); + }; +}; + +var selection_select = function(select) { + if (typeof select !== "function") select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } + } + + return new Selection(subgroups, this._parents); +}; + +function empty() { + return []; +} + +var selectorAll = function(selector) { + return selector == null ? empty : function() { + return this.querySelectorAll(selector); + }; +}; + +var selection_selectAll = function(select) { + if (typeof select !== "function") select = selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } + + return new Selection(subgroups, parents); +}; + +var selection_filter = function(match) { + if (typeof match !== "function") match = matcher$1(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Selection(subgroups, this._parents); +}; + +var sparse = function(update) { + return new Array(update.length); +}; + +var selection_enter = function() { + return new Selection(this._enter || this._groups.map(sparse), this._parents); +}; + +function EnterNode(parent, datum) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum; +} + +EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, + insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, + querySelector: function(selector) { return this._parent.querySelector(selector); }, + querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } +}; + +var constant$5 = function(x) { + return function() { + return x; + }; +}; + +var keyPrefix = "$"; // Protect against keys like “__proto__”. + +function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, + node, + groupLength = group.length, + dataLength = data.length; + + // Put any non-null nodes that fit into update. + // Put any null nodes into enter. + // Put any remaining data into enter. + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Put any non-null nodes that don’t fit into exit. + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } +} + +function bindKey(parent, group, enter, update, exit, data, key) { + var i, + node, + nodeByKeyValue = {}, + groupLength = group.length, + dataLength = data.length, + keyValues = new Array(groupLength), + keyValue; + + // Compute the key for each node. + // If multiple nodes have the same key, the duplicates are added to exit. + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); + if (keyValue in nodeByKeyValue) { + exit[i] = node; + } else { + nodeByKeyValue[keyValue] = node; + } + } + } + + // Compute the key for each datum. + // If there a node associated with this key, join and add it to update. + // If there is not (or the key is a duplicate), add it to enter. + for (i = 0; i < dataLength; ++i) { + keyValue = keyPrefix + key.call(parent, data[i], i, data); + if (node = nodeByKeyValue[keyValue]) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue[keyValue] = null; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Add any remaining nodes that were not bound to data to exit. + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { + exit[i] = node; + } + } +} + +var selection_data = function(value, key) { + if (!value) { + data = new Array(this.size()), j = -1; + this.each(function(d) { data[++j] = d; }); + return data; + } + + var bind = key ? bindKey : bindIndex, + parents = this._parents, + groups = this._groups; + + if (typeof value !== "function") value = constant$5(value); + + for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { + var parent = parents[j], + group = groups[j], + groupLength = group.length, + data = value.call(parent, parent && parent.__data__, j, parents), + dataLength = data.length, + enterGroup = enter[j] = new Array(dataLength), + updateGroup = update[j] = new Array(dataLength), + exitGroup = exit[j] = new Array(groupLength); + + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); + + // Now connect the enter nodes to their following update node, such that + // appendChild can insert the materialized enter node before this node, + // rather than at the end of the parent node. + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength); + previous._next = next || null; + } + } + } + + update = new Selection(update, parents); + update._enter = enter; + update._exit = exit; + return update; +}; + +var selection_exit = function() { + return new Selection(this._exit || this._groups.map(sparse), this._parents); +}; + +var selection_merge = function(selection) { + + for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Selection(merges, this._parents); +}; + +var selection_order = function() { + + for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { + for (var group = groups[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; +}; + +var selection_sort = function(compare) { + if (!compare) compare = ascending$2; + + function compareNode(a, b) { + return a && b ? compare(a.__data__, b.__data__) : !a - !b; + } + + for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } + } + sortgroup.sort(compareNode); + } + + return new Selection(sortgroups, this._parents).order(); +}; + +function ascending$2(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +} + +var selection_call = function() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; +}; + +var selection_nodes = function() { + var nodes = new Array(this.size()), i = -1; + this.each(function() { nodes[++i] = this; }); + return nodes; +}; + +var selection_node = function() { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) return node; + } + } + + return null; +}; + +var selection_size = function() { + var size = 0; + this.each(function() { ++size; }); + return size; +}; + +var selection_empty = function() { + return !this.node(); +}; + +var selection_each = function(callback) { + + for (var groups = this._groups, 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.call(node, node.__data__, i, group); + } + } + + return this; +}; + +function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; +} + +function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; +} + +function attrConstant(name, value) { + return function() { + this.setAttribute(name, value); + }; +} + +function attrConstantNS(fullname, value) { + return function() { + this.setAttributeNS(fullname.space, fullname.local, value); + }; +} + +function attrFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttribute(name); + else this.setAttribute(name, v); + }; +} + +function attrFunctionNS(fullname, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttributeNS(fullname.space, fullname.local); + else this.setAttributeNS(fullname.space, fullname.local, v); + }; +} + +var selection_attr = function(name, value) { + var fullname = namespace(name); + + if (arguments.length < 2) { + var node = this.node(); + return fullname.local + ? node.getAttributeNS(fullname.space, fullname.local) + : node.getAttribute(fullname); + } + + return this.each((value == null + ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" + ? (fullname.local ? attrFunctionNS : attrFunction) + : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); +}; + +var window = function(node) { + return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node + || (node.document && node) // node is a Window + || node.defaultView; // node is a Document +}; + +function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; +} + +function styleConstant(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; +} + +function styleFunction(name, value, priority) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.style.removeProperty(name); + else this.style.setProperty(name, v, priority); + }; +} + +var selection_style = function(name, value, priority) { + var node; + return arguments.length > 1 + ? this.each((value == null + ? styleRemove : typeof value === "function" + ? styleFunction + : styleConstant)(name, value, priority == null ? "" : priority)) + : window(node = this.node()) + .getComputedStyle(node, null) + .getPropertyValue(name); +}; + +function propertyRemove(name) { + return function() { + delete this[name]; + }; +} + +function propertyConstant(name, value) { + return function() { + this[name] = value; + }; +} + +function propertyFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) delete this[name]; + else this[name] = v; + }; +} + +var selection_property = function(name, value) { + return arguments.length > 1 + ? this.each((value == null + ? propertyRemove : typeof value === "function" + ? propertyFunction + : propertyConstant)(name, value)) + : this.node()[name]; +}; + +function classArray(string) { + return string.trim().split(/^|\s+/); +} + +function classList(node) { + return node.classList || new ClassList(node); +} + +function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); +} + +ClassList.prototype = { + add: function(name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function(name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function(name) { + return this._names.indexOf(name) >= 0; + } +}; + +function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.add(names[i]); +} + +function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.remove(names[i]); +} + +function classedTrue(names) { + return function() { + classedAdd(this, names); + }; +} + +function classedFalse(names) { + return function() { + classedRemove(this, names); + }; +} + +function classedFunction(names, value) { + return function() { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; +} + +var selection_classed = function(name, value) { + var names = classArray(name + ""); + + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) if (!list.contains(names[i])) return false; + return true; + } + + return this.each((typeof value === "function" + ? classedFunction : value + ? classedTrue + : classedFalse)(names, value)); +}; + +function textRemove() { + this.textContent = ""; +} + +function textConstant(value) { + return function() { + this.textContent = value; + }; +} + +function textFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + }; +} + +var selection_text = function(value) { + return arguments.length + ? this.each(value == null + ? textRemove : (typeof value === "function" + ? textFunction + : textConstant)(value)) + : this.node().textContent; +}; + +function htmlRemove() { + this.innerHTML = ""; +} + +function htmlConstant(value) { + return function() { + this.innerHTML = value; + }; +} + +function htmlFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + }; +} + +var selection_html = function(value) { + return arguments.length + ? this.each(value == null + ? htmlRemove : (typeof value === "function" + ? htmlFunction + : htmlConstant)(value)) + : this.node().innerHTML; +}; + +function raise$1() { + if (this.nextSibling) this.parentNode.appendChild(this); +} + +var selection_raise = function() { + return this.each(raise$1); +}; + +function lower() { + if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); +} + +var selection_lower = function() { + return this.each(lower); +}; + +var selection_append = function(name) { + var create = typeof name === "function" ? name : creator(name); + return this.select(function() { + return this.appendChild(create.apply(this, arguments)); + }); +}; + +function constantNull() { + return null; +} + +var selection_insert = function(name, before) { + var create = typeof name === "function" ? name : creator(name), + select = before == null ? constantNull : typeof before === "function" ? before : selector(before); + return this.select(function() { + return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); + }); +}; + +function remove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); +} + +var selection_remove = function() { + return this.each(remove); +}; + +var selection_datum = function(value) { + return arguments.length + ? this.property("__data__", value) + : this.node().__data__; +}; + +function dispatchEvent(node, type, params) { + var window$$1 = window(node), + event = window$$1.CustomEvent; + + if (event) { + event = new event(type, params); + } else { + event = window$$1.document.createEvent("Event"); + if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; + else event.initEvent(type, false, false); + } + + node.dispatchEvent(event); +} + +function dispatchConstant(type, params) { + return function() { + return dispatchEvent(this, type, params); + }; +} + +function dispatchFunction(type, params) { + return function() { + return dispatchEvent(this, type, params.apply(this, arguments)); + }; +} + +var selection_dispatch = function(type, params) { + return this.each((typeof params === "function" + ? dispatchFunction + : dispatchConstant)(type, params)); +}; + +var root = [null]; + +function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; +} + +function selection() { + return new Selection([[document.documentElement]], root); +} + +Selection.prototype = selection.prototype = { + constructor: Selection, + select: selection_select, + selectAll: selection_selectAll, + filter: selection_filter, + data: selection_data, + enter: selection_enter, + exit: selection_exit, + merge: selection_merge, + order: selection_order, + sort: selection_sort, + call: selection_call, + nodes: selection_nodes, + node: selection_node, + size: selection_size, + empty: selection_empty, + each: selection_each, + attr: selection_attr, + style: selection_style, + property: selection_property, + classed: selection_classed, + text: selection_text, + html: selection_html, + raise: selection_raise, + lower: selection_lower, + append: selection_append, + insert: selection_insert, + remove: selection_remove, + datum: selection_datum, + on: selection_on, + dispatch: selection_dispatch +}; + +var select = function(selector) { + return typeof selector === "string" + ? new Selection([[document.querySelector(selector)]], [document.documentElement]) + : new Selection([[selector]], root); +}; + +var selectAll = function(selector) { + return typeof selector === "string" + ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) + : new Selection([selector == null ? [] : selector], root); +}; + +var touch = function(node, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; + + for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return point$5(node, touch); + } + } + + return null; +}; + +var touches = function(node, touches) { + if (touches == null) touches = sourceEvent().touches; + + for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { + points[i] = point$5(node, touches[i]); + } + + return points; +}; + +var emptyOn = dispatch("start", "end", "interrupt"); +var emptyTween = []; + +var CREATED = 0; +var SCHEDULED = 1; +var STARTING = 2; +var STARTED = 3; +var RUNNING = 4; +var ENDING = 5; +var ENDED = 6; + +var schedule = function(node, name, id, index, group, timing) { + var schedules = node.__transition; + if (!schedules) node.__transition = {}; + else if (id in schedules) return; + create(node, id, { + name: name, + index: index, // For context during callback. + group: group, // For context during callback. + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); +}; + +function init(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late"); + return schedule; +} + +function set$3(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); + return schedule; +} + +function get$1(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id])) throw new Error("too late"); + return schedule; +} + +function create(node, id, self) { + var schedules = node.__transition, + tween; + + // Initialize the self timer when the transition is created. + // Note the actual delay is not known until the first callback! + schedules[id] = self; + self.timer = timer(schedule, 0, self.time); + + function schedule(elapsed) { + self.state = SCHEDULED; + self.timer.restart(start, self.delay, self.time); + + // If the elapsed delay is less than our first sleep, start immediately. + if (self.delay <= elapsed) start(elapsed - self.delay); + } + + function start(elapsed) { + var i, j, n, o; + + // If the state is not SCHEDULED, then we previously errored on start. + if (self.state !== SCHEDULED) return stop(); + + for (i in schedules) { + o = schedules[i]; + if (o.name !== self.name) continue; + + // While this element already has a starting transition during this frame, + // defer starting an interrupting transition until that transition has a + // chance to tick (and possibly end); see d3/d3-transition#54! + if (o.state === STARTED) return timeout$1(start); + + // Interrupt the active transition, if any. + // Dispatch the interrupt event. + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + + // Cancel any pre-empted transitions. No interrupt event is dispatched + // because the cancelled transitions never started. Note that this also + // removes this transition from the pending list! + else if (+i < id) { + o.state = ENDED; + o.timer.stop(); + delete schedules[i]; + } + } + + // Defer the first tick to end of the current frame; see d3/d3#1576. + // Note the transition may be canceled after start and before the first tick! + // Note this must be scheduled before the start event; see d3/d3-transition#16! + // Assuming this is successful, subsequent callbacks go straight to tick. + timeout$1(function() { + if (self.state === STARTED) { + self.state = RUNNING; + self.timer.restart(tick, self.delay, self.time); + tick(elapsed); + } + }); + + // Dispatch the start event. + // Note this must be done before the tween are initialized. + self.state = STARTING; + self.on.call("start", node, node.__data__, self.index, self.group); + if (self.state !== STARTING) return; // interrupted + self.state = STARTED; + + // Initialize the tween, deleting null tween. + tween = new Array(n = self.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + + function tick(elapsed) { + var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), + i = -1, + n = tween.length; + + while (++i < n) { + tween[i].call(null, t); + } + + // Dispatch the end event. + if (self.state === ENDING) { + self.on.call("end", node, node.__data__, self.index, self.group); + stop(); + } + } + + function stop() { + self.state = ENDED; + self.timer.stop(); + delete schedules[id]; + for (var i in schedules) return; // eslint-disable-line no-unused-vars + delete node.__transition; + } +} + +var interrupt = function(node, name) { + var schedules = node.__transition, + schedule, + active, + empty = true, + i; + + if (!schedules) return; + + name = name == null ? null : name + ""; + + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { empty = false; continue; } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + + if (empty) delete node.__transition; +}; + +var selection_interrupt = function(name) { + return this.each(function() { + interrupt(this, name); + }); +}; + +function tweenRemove(id, name) { + var tween0, tween1; + return function() { + var schedule = set$3(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + + schedule.tween = tween1; + }; +} + +function tweenFunction(id, name, value) { + var tween0, tween1; + if (typeof value !== "function") throw new Error; + return function() { + var schedule = set$3(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) tween1.push(t); + } + + schedule.tween = tween1; + }; +} + +var transition_tween = function(name, value) { + var id = this._id; + + name += ""; + + if (arguments.length < 2) { + var tween = get$1(this.node(), id).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + + return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); +}; + +function tweenValue(transition, name, value) { + var id = transition._id; + + transition.each(function() { + var schedule = set$3(this, id); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + + return function(node) { + return get$1(node, id).value[name]; + }; +} + +var interpolate$1 = function(a, b) { + var c; + return (typeof b === "number" ? interpolateNumber + : b instanceof color ? interpolateRgb + : (c = color(b)) ? (b = c, interpolateRgb) + : interpolateString)(a, b); +}; + +function attrRemove$1(name) { + return function() { + this.removeAttribute(name); + }; +} + +function attrRemoveNS$1(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; +} + +function attrConstant$1(name, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function attrConstantNS$1(fullname, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function attrFunction$1(name, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttribute(name); + value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +function attrFunctionNS$1(fullname, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); + value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +var transition_attr = function(name, value) { + var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$1; + return this.attrTween(name, typeof value === "function" + ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) + : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) + : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value)); +}; + +function attrTweenNS(fullname, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttributeNS(fullname.space, fullname.local, i(t)); + }; + } + tween._value = value; + return tween; +} + +function attrTween(name, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttribute(name, i(t)); + }; + } + tween._value = value; + return tween; +} + +var transition_attrTween = function(name, value) { + var key = "attr." + name; + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + var fullname = namespace(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); +}; + +function delayFunction(id, value) { + return function() { + init(this, id).delay = +value.apply(this, arguments); + }; +} + +function delayConstant(id, value) { + return value = +value, function() { + init(this, id).delay = value; + }; +} + +var transition_delay = function(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? delayFunction + : delayConstant)(id, value)) + : get$1(this.node(), id).delay; +}; + +function durationFunction(id, value) { + return function() { + set$3(this, id).duration = +value.apply(this, arguments); + }; +} + +function durationConstant(id, value) { + return value = +value, function() { + set$3(this, id).duration = value; + }; +} + +var transition_duration = function(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? durationFunction + : durationConstant)(id, value)) + : get$1(this.node(), id).duration; +}; + +function easeConstant(id, value) { + if (typeof value !== "function") throw new Error; + return function() { + set$3(this, id).ease = value; + }; +} + +var transition_ease = function(value) { + var id = this._id; + + return arguments.length + ? this.each(easeConstant(id, value)) + : get$1(this.node(), id).ease; +}; + +var transition_filter = function(match) { + if (typeof match !== "function") match = matcher$1(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Transition(subgroups, this._parents, this._name, this._id); +}; + +var transition_merge = function(transition) { + if (transition._id !== this._id) throw new Error; + + for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Transition(merges, this._parents, this._name, this._id); +}; + +function start$1(name) { + return (name + "").trim().split(/^|\s+/).every(function(t) { + var i = t.indexOf("."); + if (i >= 0) t = t.slice(0, i); + return !t || t === "start"; + }); +} + +function onFunction(id, name, listener) { + var on0, on1, sit = start$1(name) ? init : set$3; + return function() { + var schedule = sit(this, id), + on = schedule.on; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); + + schedule.on = on1; + }; +} + +var transition_on = function(name, listener) { + var id = this._id; + + return arguments.length < 2 + ? get$1(this.node(), id).on.on(name) + : this.each(onFunction(id, name, listener)); +}; + +function removeFunction(id) { + return function() { + var parent = this.parentNode; + for (var i in this.__transition) if (+i !== id) return; + if (parent) parent.removeChild(this); + }; +} + +var transition_remove = function() { + return this.on("end.remove", removeFunction(this._id)); +}; + +var transition_select = function(select$$1) { + var name = this._name, + id = this._id; + + if (typeof select$$1 !== "function") select$$1 = selector(select$$1); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule(subgroup[i], name, id, i, subgroup, get$1(node, id)); + } + } + } + + return new Transition(subgroups, this._parents, name, id); +}; + +var transition_selectAll = function(select$$1) { + var name = this._name, + id = this._id; + + if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children = select$$1.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) { + if (child = children[k]) { + schedule(child, name, id, k, children, inherit); + } + } + subgroups.push(children); + parents.push(node); + } + } + } + + return new Transition(subgroups, parents, name, id); +}; + +var Selection$1 = selection.prototype.constructor; + +var transition_selection = function() { + return new Selection$1(this._groups, this._parents); +}; + +function styleRemove$1(name, interpolate$$1) { + var value00, + value10, + interpolate0; + return function() { + var style = window(this).getComputedStyle(this, null), + value0 = style.getPropertyValue(name), + value1 = (this.style.removeProperty(name), style.getPropertyValue(name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +function styleRemoveEnd(name) { + return function() { + this.style.removeProperty(name); + }; +} + +function styleConstant$1(name, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = window(this).getComputedStyle(this, null).getPropertyValue(name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function styleFunction$1(name, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var style = window(this).getComputedStyle(this, null), + value0 = style.getPropertyValue(name), + value1 = value(this); + if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +var transition_style = function(name, value, priority) { + var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$1; + return value == null ? this + .styleTween(name, styleRemove$1(name, i)) + .on("end.style." + name, styleRemoveEnd(name)) + : this.styleTween(name, typeof value === "function" + ? styleFunction$1(name, i, tweenValue(this, "style." + name, value)) + : styleConstant$1(name, i, value), priority); +}; + +function styleTween(name, value, priority) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.style.setProperty(name, i(t), priority); + }; + } + tween._value = value; + return tween; +} + +var transition_styleTween = function(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); +}; + +function textConstant$1(value) { + return function() { + this.textContent = value; + }; +} + +function textFunction$1(value) { + return function() { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; +} + +var transition_text = function(value) { + return this.tween("text", typeof value === "function" + ? textFunction$1(tweenValue(this, "text", value)) + : textConstant$1(value == null ? "" : value + "")); +}; + +var transition_transition = function() { + var name = this._name, + id0 = this._id, + id1 = newId(); + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit = get$1(node, id0); + schedule(node, name, id1, i, group, { + time: inherit.time + inherit.delay + inherit.duration, + delay: 0, + duration: inherit.duration, + ease: inherit.ease + }); + } + } + } + + return new Transition(groups, this._parents, name, id1); +}; + +var id = 0; + +function Transition(groups, parents, name, id) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id; +} + +function transition(name) { + return selection().transition(name); +} + +function newId() { + return ++id; +} + +var selection_prototype = selection.prototype; + +Transition.prototype = transition.prototype = { + constructor: Transition, + select: transition_select, + selectAll: transition_selectAll, + filter: transition_filter, + merge: transition_merge, + selection: transition_selection, + transition: transition_transition, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: transition_on, + attr: transition_attr, + attrTween: transition_attrTween, + style: transition_style, + styleTween: transition_styleTween, + text: transition_text, + remove: transition_remove, + tween: transition_tween, + delay: transition_delay, + duration: transition_duration, + ease: transition_ease +}; + +var defaultTiming = { + time: null, // Set on use. + delay: 0, + duration: 250, + ease: cubicInOut +}; + +function inherit(node, id) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id])) { + if (!(node = node.parentNode)) { + return defaultTiming.time = now(), defaultTiming; + } + } + return timing; +} + +var selection_transition = function(name) { + var id, + timing; + + if (name instanceof Transition) { + id = name._id, name = name._name; + } else { + id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; + } + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule(node, name, id, i, group, timing || inherit(node, id)); + } + } + } + + return new Transition(groups, this._parents, name, id); +}; + +selection.prototype.interrupt = selection_interrupt; +selection.prototype.transition = selection_transition; + +var root$1 = [null]; + +var active = function(node, name) { + var schedules = node.__transition, + schedule, + i; + + if (schedules) { + name = name == null ? null : name + ""; + for (i in schedules) { + if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { + return new Transition([[node]], root$1, name, +i); + } + } + } + + return null; +}; + +var slice$4 = Array.prototype.slice; + +var identity$5 = function(x) { + return x; +}; + +var top = 1; +var right = 2; +var bottom = 3; +var left = 4; +var epsilon$2 = 1e-6; + +function translateX(scale0, scale1, d) { + var x = scale0(d); + return "translate(" + (isFinite(x) ? x : scale1(d)) + ",0)"; +} + +function translateY(scale0, scale1, d) { + var y = scale0(d); + return "translate(0," + (isFinite(y) ? y : scale1(d)) + ")"; +} + +function center(scale) { + var offset = scale.bandwidth() / 2; + if (scale.round()) offset = Math.round(offset); + return function(d) { + return scale(d) + offset; + }; +} + +function entering() { + return !this.__axis; +} + +function axis(orient, scale) { + var tickArguments = [], + tickValues = null, + tickFormat = null, + tickSizeInner = 6, + tickSizeOuter = 6, + tickPadding = 3; + + function axis(context) { + var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, + format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$5) : tickFormat, + spacing = Math.max(tickSizeInner, 0) + tickPadding, + transform = orient === top || orient === bottom ? translateX : translateY, + range = scale.range(), + range0 = range[0] + 0.5, + range1 = range[range.length - 1] + 0.5, + position = (scale.bandwidth ? center : identity$5)(scale.copy()), + selection = context.selection ? context.selection() : context, + path = selection.selectAll(".domain").data([null]), + tick = selection.selectAll(".tick").data(values, scale).order(), + tickExit = tick.exit(), + tickEnter = tick.enter().append("g").attr("class", "tick"), + line = tick.select("line"), + text = tick.select("text"), + k = orient === top || orient === left ? -1 : 1, + x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x"); + + path = path.merge(path.enter().insert("path", ".tick") + .attr("class", "domain") + .attr("stroke", "#000")); + + tick = tick.merge(tickEnter); + + line = line.merge(tickEnter.append("line") + .attr("stroke", "#000") + .attr(x + "2", k * tickSizeInner) + .attr(y + "1", 0.5) + .attr(y + "2", 0.5)); + + text = text.merge(tickEnter.append("text") + .attr("fill", "#000") + .attr(x, k * spacing) + .attr(y, 0.5) + .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); + + if (context !== selection) { + path = path.transition(context); + tick = tick.transition(context); + line = line.transition(context); + text = text.transition(context); + + tickExit = tickExit.transition(context) + .attr("opacity", epsilon$2) + .attr("transform", function(d) { return transform(position, this.parentNode.__axis || position, d); }); + + tickEnter + .attr("opacity", epsilon$2) + .attr("transform", function(d) { return transform(this.parentNode.__axis || position, position, d); }); + } + + tickExit.remove(); + + path + .attr("d", orient === left || orient == right + ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter + : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter); + + tick + .attr("opacity", 1) + .attr("transform", function(d) { return transform(position, position, d); }); + + line + .attr(x + "2", k * tickSizeInner); + + text + .attr(x, k * spacing) + .text(format); + + selection.filter(entering) + .attr("fill", "none") + .attr("font-size", 10) + .attr("font-family", "sans-serif") + .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); + + selection + .each(function() { this.__axis = position; }); + } + + axis.scale = function(_) { + return arguments.length ? (scale = _, axis) : scale; + }; + + axis.ticks = function() { + return tickArguments = slice$4.call(arguments), axis; + }; + + axis.tickArguments = function(_) { + return arguments.length ? (tickArguments = _ == null ? [] : slice$4.call(_), axis) : tickArguments.slice(); + }; + + axis.tickValues = function(_) { + return arguments.length ? (tickValues = _ == null ? null : slice$4.call(_), axis) : tickValues && tickValues.slice(); + }; + + axis.tickFormat = function(_) { + return arguments.length ? (tickFormat = _, axis) : tickFormat; + }; + + axis.tickSize = function(_) { + return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; + }; + + axis.tickSizeInner = function(_) { + return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; + }; + + axis.tickSizeOuter = function(_) { + return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; + }; + + axis.tickPadding = function(_) { + return arguments.length ? (tickPadding = +_, axis) : tickPadding; + }; + + return axis; +} + +function axisTop(scale) { + return axis(top, scale); +} + +function axisRight(scale) { + return axis(right, scale); +} + +function axisBottom(scale) { + return axis(bottom, scale); +} + +function axisLeft(scale) { + return axis(left, scale); +} + +function defaultSeparation(a, b) { + return a.parent === b.parent ? 1 : 2; +} + +function meanX(children) { + return children.reduce(meanXReduce, 0) / children.length; +} + +function meanXReduce(x, c) { + return x + c.x; +} + +function maxY(children) { + return 1 + children.reduce(maxYReduce, 0); +} + +function maxYReduce(y, c) { + return Math.max(y, c.y); +} + +function leafLeft(node) { + var children; + while (children = node.children) node = children[0]; + return node; +} + +function leafRight(node) { + var children; + while (children = node.children) node = children[children.length - 1]; + return node; +} + +var cluster = function() { + var separation = defaultSeparation, + dx = 1, + dy = 1, + nodeSize = false; + + function cluster(root) { + var previousNode, + x = 0; + + // First walk, computing the initial x & y values. + root.eachAfter(function(node) { + var children = node.children; + if (children) { + node.x = meanX(children); + node.y = maxY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + + var left = leafLeft(root), + right = leafRight(root), + x0 = left.x - separation(left, right) / 2, + x1 = right.x + separation(right, left) / 2; + + // Second walk, normalizing x & y to the desired size. + return root.eachAfter(nodeSize ? function(node) { + node.x = (node.x - root.x) * dx; + node.y = (root.y - node.y) * dy; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * dx; + node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; + }); + } + + cluster.separation = function(x) { + return arguments.length ? (separation = x, cluster) : separation; + }; + + cluster.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); + }; + + cluster.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); + }; + + return cluster; +}; + +var node_each = function(callback) { + var node = this, current, next = [node], children, i, n; + do { + current = next.reverse(), next = []; + while (node = current.pop()) { + callback(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + next.push(children[i]); + } + } + } while (next.length); + return this; +}; + +var node_eachBefore = function(callback) { + var node = this, nodes = [node], children, i; + while (node = nodes.pop()) { + callback(node), children = node.children; + if (children) for (i = children.length - 1; i >= 0; --i) { + nodes.push(children[i]); + } + } + return this; +}; + +var node_eachAfter = function(callback) { + var node = this, nodes = [node], next = [], children, i, n; + while (node = nodes.pop()) { + next.push(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + nodes.push(children[i]); + } + } + while (node = next.pop()) { + callback(node); + } + return this; +}; + +var node_sum = function(value) { + return this.eachAfter(function(node) { + var sum = +value(node.data) || 0, + children = node.children, + i = children && children.length; + while (--i >= 0) sum += children[i].value; + node.value = sum; + }); +}; + +var node_sort = function(compare) { + return this.eachBefore(function(node) { + if (node.children) { + node.children.sort(compare); + } + }); +}; + +var node_path = function(end) { + var start = this, + ancestor = leastCommonAncestor(start, end), + nodes = [start]; + while (start !== ancestor) { + start = start.parent; + nodes.push(start); + } + var k = nodes.length; + while (end !== ancestor) { + nodes.splice(k, 0, end); + end = end.parent; + } + return nodes; +}; + +function leastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = a.ancestors(), + bNodes = b.ancestors(), + c = null; + a = aNodes.pop(); + b = bNodes.pop(); + while (a === b) { + c = a; + a = aNodes.pop(); + b = bNodes.pop(); + } + return c; +} + +var node_ancestors = function() { + var node = this, nodes = [node]; + while (node = node.parent) { + nodes.push(node); + } + return nodes; +}; + +var node_descendants = function() { + var nodes = []; + this.each(function(node) { + nodes.push(node); + }); + return nodes; +}; + +var node_leaves = function() { + var leaves = []; + this.eachBefore(function(node) { + if (!node.children) { + leaves.push(node); + } + }); + return leaves; +}; + +var node_links = function() { + var root = this, links = []; + root.each(function(node) { + if (node !== root) { // Don’t include the root’s parent, if any. + links.push({source: node.parent, target: node}); + } + }); + return links; +}; + +function hierarchy(data, children) { + var root = new Node(data), + valued = +data.value && (root.value = data.value), + node, + nodes = [root], + child, + childs, + i, + n; + + if (children == null) children = defaultChildren; + + while (node = nodes.pop()) { + if (valued) node.value = +node.data.value; + if ((childs = children(node.data)) && (n = childs.length)) { + node.children = new Array(n); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new Node(childs[i])); + child.parent = node; + child.depth = node.depth + 1; + } + } + } + + return root.eachBefore(computeHeight); +} + +function node_copy() { + return hierarchy(this).eachBefore(copyData); +} + +function defaultChildren(d) { + return d.children; +} + +function copyData(node) { + node.data = node.data.data; +} + +function computeHeight(node) { + var height = 0; + do node.height = height; + while ((node = node.parent) && (node.height < ++height)); +} + +function Node(data) { + this.data = data; + this.depth = + this.height = 0; + this.parent = null; +} + +Node.prototype = hierarchy.prototype = { + constructor: Node, + each: node_each, + eachAfter: node_eachAfter, + eachBefore: node_eachBefore, + sum: node_sum, + sort: node_sort, + path: node_path, + ancestors: node_ancestors, + descendants: node_descendants, + leaves: node_leaves, + links: node_links, + copy: node_copy +}; + +function Node$2(value) { + this._ = value; + this.next = null; +} + +var shuffle$1 = function(array) { + var i, + n = (array = array.slice()).length, + head = null, + node = head; + + while (n) { + var next = new Node$2(array[n - 1]); + if (node) node = node.next = next; + else node = head = next; + array[i] = array[--n]; + } + + return { + head: head, + tail: node + }; +}; + +var enclose = function(circles) { + return encloseN(shuffle$1(circles), []); +}; + +function encloses(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r - b.r; + return dr * dr + 1e-6 > dx * dx + dy * dy; +} + +// Returns the smallest circle that contains circles L and intersects circles B. +function encloseN(L, B) { + var circle, + l0 = null, + l1 = L.head, + l2, + p1; + + switch (B.length) { + case 1: circle = enclose1(B[0]); break; + case 2: circle = enclose2(B[0], B[1]); break; + case 3: circle = enclose3(B[0], B[1], B[2]); break; + } + + while (l1) { + p1 = l1._, l2 = l1.next; + if (!circle || !encloses(circle, p1)) { + + // Temporarily truncate L before l1. + if (l0) L.tail = l0, l0.next = null; + else L.head = L.tail = null; + + B.push(p1); + circle = encloseN(L, B); // Note: reorders L! + B.pop(); + + // Move l1 to the front of L and reconnect the truncated list L. + if (L.head) l1.next = L.head, L.head = l1; + else l1.next = null, L.head = L.tail = l1; + l0 = L.tail, l0.next = l2; + + } else { + l0 = l1; + } + l1 = l2; + } + + L.tail = l0; + return circle; +} + +function enclose1(a) { + return { + x: a.x, + y: a.y, + r: a.r + }; +} + +function enclose2(a, b) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, + l = Math.sqrt(x21 * x21 + y21 * y21); + return { + x: (x1 + x2 + x21 / l * r21) / 2, + y: (y1 + y2 + y21 / l * r21) / 2, + r: (l + r1 + r2) / 2 + }; +} + +function enclose3(a, b, c) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x3 = c.x, y3 = c.y, r3 = c.r, + a2 = 2 * (x1 - x2), + b2 = 2 * (y1 - y2), + c2 = 2 * (r2 - r1), + d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2, + a3 = 2 * (x1 - x3), + b3 = 2 * (y1 - y3), + c3 = 2 * (r3 - r1), + d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3, + ab = a3 * b2 - a2 * b3, + xa = (b2 * d3 - b3 * d2) / ab - x1, + xb = (b3 * c2 - b2 * c3) / ab, + ya = (a3 * d2 - a2 * d3) / ab - y1, + yb = (a2 * c3 - a3 * c2) / ab, + A = xb * xb + yb * yb - 1, + B = 2 * (xa * xb + ya * yb + r1), + C = xa * xa + ya * ya - r1 * r1, + r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A); + return { + x: xa + xb * r + x1, + y: ya + yb * r + y1, + r: r + }; +} + +function place(a, b, c) { + var ax = a.x, + ay = a.y, + da = b.r + c.r, + db = a.r + c.r, + dx = b.x - ax, + dy = b.y - ay, + dc = dx * dx + dy * dy; + if (dc) { + var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), + y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = ax + x * dx + y * dy; + c.y = ay + x * dy - y * dx; + } else { + c.x = ax + db; + c.y = ay; + } +} + +function intersects(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r + b.r; + return dr * dr > dx * dx + dy * dy; +} + +function distance2(circle, x, y) { + var dx = circle.x - x, + dy = circle.y - y; + return dx * dx + dy * dy; +} + +function Node$1(circle) { + this._ = circle; + this.next = null; + this.previous = null; +} + +function packEnclose(circles) { + if (!(n = circles.length)) return 0; + + var a, b, c, n; + + // Place the first circle. + a = circles[0], a.x = 0, a.y = 0; + if (!(n > 1)) return a.r; + + // Place the second circle. + b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; + if (!(n > 2)) return a.r + b.r; + + // Place the third circle. + place(b, a, c = circles[2]); + + // Initialize the weighted centroid. + var aa = a.r * a.r, + ba = b.r * b.r, + ca = c.r * c.r, + oa = aa + ba + ca, + ox = aa * a.x + ba * b.x + ca * c.x, + oy = aa * a.y + ba * b.y + ca * c.y, + cx, cy, i, j, k, sj, sk; + + // Initialize the front-chain using the first three circles a, b and c. + a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); + a.next = c.previous = b; + b.next = a.previous = c; + c.next = b.previous = a; + + // Attempt to place each remaining circle… + pack: for (i = 3; i < n; ++i) { + place(a._, b._, c = circles[i]), c = new Node$1(c); + + // If there are only three elements in the front-chain… + if ((k = a.previous) === (j = b.next)) { + // If the new circle intersects the third circle, + // rotate the front chain to try the next position. + if (intersects(j._, c._)) { + a = b, b = j, --i; + continue pack; + } + } + + // Find the closest intersecting circle on the front-chain, if any. + else { + sj = j._.r, sk = k._.r; + do { + if (sj <= sk) { + if (intersects(j._, c._)) { + b = j, a.next = b, b.previous = a, --i; + continue pack; + } + j = j.next, sj += j._.r; + } else { + if (intersects(k._, c._)) { + a = k, a.next = b, b.previous = a, --i; + continue pack; + } + k = k.previous, sk += k._.r; + } + } while (j !== k.next); + } + + // Success! Insert the new circle c between a and b. + c.previous = a, c.next = b, a.next = b.previous = b = c; + + // Update the weighted centroid. + oa += ca = c._.r * c._.r; + ox += ca * c._.x; + oy += ca * c._.y; + + // Compute the new closest circle a to centroid. + aa = distance2(a._, cx = ox / oa, cy = oy / oa); + while ((c = c.next) !== b) { + if ((ca = distance2(c._, cx, cy)) < aa) { + a = c, aa = ca; + } + } + b = a.next; + } + + // Compute the enclosing circle of the front chain. + a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); + + // Translate the circles to put the enclosing circle around the origin. + for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; + + return c.r; +} + +var siblings = function(circles) { + packEnclose(circles); + return circles; +}; + +function optional(f) { + return f == null ? null : required(f); +} + +function required(f) { + if (typeof f !== "function") throw new Error; + return f; +} + +function constantZero() { + return 0; +} + +var constant$6 = function(x) { + return function() { + return x; + }; +}; + +function defaultRadius(d) { + return Math.sqrt(d.value); +} + +var index = function() { + var radius = null, + dx = 1, + dy = 1, + padding = constantZero; + + function pack(root) { + root.x = dx / 2, root.y = dy / 2; + if (radius) { + root.eachBefore(radiusLeaf(radius)) + .eachAfter(packChildren(padding, 0.5)) + .eachBefore(translateChild(1)); + } else { + root.eachBefore(radiusLeaf(defaultRadius)) + .eachAfter(packChildren(constantZero, 1)) + .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) + .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); + } + return root; + } + + pack.radius = function(x) { + return arguments.length ? (radius = optional(x), pack) : radius; + }; + + pack.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; + }; + + pack.padding = function(x) { + return arguments.length ? (padding = typeof x === "function" ? x : constant$6(+x), pack) : padding; + }; + + return pack; +}; + +function radiusLeaf(radius) { + return function(node) { + if (!node.children) { + node.r = Math.max(0, +radius(node) || 0); + } + }; +} + +function packChildren(padding, k) { + return function(node) { + if (children = node.children) { + var children, + i, + n = children.length, + r = padding(node) * k || 0, + e; + + if (r) for (i = 0; i < n; ++i) children[i].r += r; + e = packEnclose(children); + if (r) for (i = 0; i < n; ++i) children[i].r -= r; + node.r = e + r; + } + }; +} + +function translateChild(k) { + return function(node) { + var parent = node.parent; + node.r *= k; + if (parent) { + node.x = parent.x + k * node.x; + node.y = parent.y + k * node.y; + } + }; +} + +var roundNode = function(node) { + node.x0 = Math.round(node.x0); + node.y0 = Math.round(node.y0); + node.x1 = Math.round(node.x1); + node.y1 = Math.round(node.y1); +}; + +var treemapDice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (x1 - x0) / parent.value; + + while (++i < n) { + node = nodes[i], node.y0 = y0, node.y1 = y1; + node.x0 = x0, node.x1 = x0 += node.value * k; + } +}; + +var partition = function() { + var dx = 1, + dy = 1, + padding = 0, + round = false; + + function partition(root) { + var n = root.height + 1; + root.x0 = + root.y0 = padding; + root.x1 = dx; + root.y1 = dy / n; + root.eachBefore(positionNode(dy, n)); + if (round) root.eachBefore(roundNode); + return root; + } + + function positionNode(dy, n) { + return function(node) { + if (node.children) { + treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); + } + var x0 = node.x0, + y0 = node.y0, + x1 = node.x1 - padding, + y1 = node.y1 - padding; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + }; + } + + partition.round = function(x) { + return arguments.length ? (round = !!x, partition) : round; + }; + + partition.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; + }; + + partition.padding = function(x) { + return arguments.length ? (padding = +x, partition) : padding; + }; + + return partition; +}; + +var keyPrefix$1 = "$"; +var preroot = {depth: -1}; +var ambiguous = {}; + +function defaultId(d) { + return d.id; +} + +function defaultParentId(d) { + return d.parentId; +} + +var stratify = function() { + var id = defaultId, + parentId = defaultParentId; + + function stratify(data) { + var d, + i, + n = data.length, + root, + parent, + node, + nodes = new Array(n), + nodeId, + nodeKey, + nodeByKey = {}; + + for (i = 0; i < n; ++i) { + d = data[i], node = nodes[i] = new Node(d); + if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { + nodeKey = keyPrefix$1 + (node.id = nodeId); + nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; + } + } + + for (i = 0; i < n; ++i) { + node = nodes[i], nodeId = parentId(data[i], i, data); + if (nodeId == null || !(nodeId += "")) { + if (root) throw new Error("multiple roots"); + root = node; + } else { + parent = nodeByKey[keyPrefix$1 + nodeId]; + if (!parent) throw new Error("missing: " + nodeId); + if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); + if (parent.children) parent.children.push(node); + else parent.children = [node]; + node.parent = parent; + } + } + + if (!root) throw new Error("no root"); + root.parent = preroot; + root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); + root.parent = null; + if (n > 0) throw new Error("cycle"); + + return root; + } + + stratify.id = function(x) { + return arguments.length ? (id = required(x), stratify) : id; + }; + + stratify.parentId = function(x) { + return arguments.length ? (parentId = required(x), stratify) : parentId; + }; + + return stratify; +}; + +function defaultSeparation$1(a, b) { + return a.parent === b.parent ? 1 : 2; +} + +// function radialSeparation(a, b) { +// return (a.parent === b.parent ? 1 : 2) / a.depth; +// } + +// This function is used to traverse the left contour of a subtree (or +// subforest). It returns the successor of v on this contour. This successor is +// either given by the leftmost child of v or by the thread of v. The function +// returns null if and only if v is on the highest level of its subtree. +function nextLeft(v) { + var children = v.children; + return children ? children[0] : v.t; +} + +// This function works analogously to nextLeft. +function nextRight(v) { + var children = v.children; + return children ? children[children.length - 1] : v.t; +} + +// Shifts the current subtree rooted at w+. This is done by increasing +// prelim(w+) and mod(w+) by shift. +function moveSubtree(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; +} + +// All other shifts, applied to the smaller subtrees between w- and w+, are +// performed by this function. To prepare the shifts, we have to adjust +// change(w+), shift(w+), and change(w-). +function executeShifts(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); + } +} + +// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, +// returns the specified (default) ancestor. +function nextAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; +} + +function TreeNode(node, i) { + this._ = node; + this.parent = null; + this.children = null; + this.A = null; // default ancestor + this.a = this; // ancestor + this.z = 0; // prelim + this.m = 0; // mod + this.c = 0; // change + this.s = 0; // shift + this.t = null; // thread + this.i = i; // number +} + +TreeNode.prototype = Object.create(Node.prototype); + +function treeRoot(root) { + var tree = new TreeNode(root, 0), + node, + nodes = [tree], + child, + children, + i, + n; + + while (node = nodes.pop()) { + if (children = node._.children) { + node.children = new Array(n = children.length); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new TreeNode(children[i], i)); + child.parent = node; + } + } + } + + (tree.parent = new TreeNode(null, 0)).children = [tree]; + return tree; +} + +// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm +var tree = function() { + var separation = defaultSeparation$1, + dx = 1, + dy = 1, + nodeSize = null; + + function tree(root) { + var t = treeRoot(root); + + // Compute the layout using Buchheim et al.’s algorithm. + t.eachAfter(firstWalk), t.parent.m = -t.z; + t.eachBefore(secondWalk); + + // If a fixed node size is specified, scale x and y. + if (nodeSize) root.eachBefore(sizeNode); + + // If a fixed tree size is specified, scale x and y based on the extent. + // Compute the left-most, right-most, and depth-most nodes for extents. + else { + var left = root, + right = root, + bottom = root; + root.eachBefore(function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var s = left === right ? 1 : separation(left, right) / 2, + tx = s - left.x, + kx = dx / (right.x + s + tx), + ky = dy / (bottom.depth || 1); + root.eachBefore(function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + + return root; + } + + // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is + // applied recursively to the children of v, as well as the function + // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the + // node v is placed to the midpoint of its outermost children. + function firstWalk(v) { + var children = v.children, + siblings = v.parent.children, + w = v.i ? siblings[v.i - 1] : null; + if (children) { + executeShifts(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]); + } + + // Computes all real x-coordinates by summing up the modifiers recursively. + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + + // The core of the algorithm. Here, a new subtree is combined with the + // previous subtrees. Threads are used to traverse the inside and outside + // contours of the left and right subtree up to the highest common level. The + // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the + // superscript o means outside and i means inside, the subscript - means left + // subtree and + means right subtree. For summing up the modifiers along the + // contour, we use respective variables si+, si-, so-, and so+. Whenever two + // nodes of the inside contours conflict, we compute the left one of the + // greatest uncommon ancestors using the function ANCESTOR and call MOVE + // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. + // Finally, we add a new thread (if necessary). + 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 = nextRight(vim), vip = nextLeft(vip), vim && vip) { + vom = nextLeft(vom); + vop = nextRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + moveSubtree(nextAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !nextRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !nextLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + + function sizeNode(node) { + node.x *= dx; + node.y = node.depth * dy; + } + + tree.separation = function(x) { + return arguments.length ? (separation = x, tree) : separation; + }; + + tree.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); + }; + + tree.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); + }; + + return tree; +}; + +var treemapSlice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (y1 - y0) / parent.value; + + while (++i < n) { + node = nodes[i], node.x0 = x0, node.x1 = x1; + node.y0 = y0, node.y1 = y0 += node.value * k; + } +}; + +var phi = (1 + Math.sqrt(5)) / 2; + +function squarifyRatio(ratio, parent, x0, y0, x1, y1) { + var rows = [], + nodes = parent.children, + row, + nodeValue, + i0 = 0, + i1, + n = nodes.length, + dx, dy, + value = parent.value, + sumValue, + minValue, + maxValue, + newRatio, + minRatio, + alpha, + beta; + + while (i0 < n) { + dx = x1 - x0, dy = y1 - y0; + minValue = maxValue = sumValue = nodes[i0].value; + alpha = Math.max(dy / dx, dx / dy) / (value * ratio); + beta = sumValue * sumValue * alpha; + minRatio = Math.max(maxValue / beta, beta / minValue); + + // Keep adding nodes while the aspect ratio maintains or improves. + for (i1 = i0 + 1; i1 < n; ++i1) { + sumValue += nodeValue = nodes[i1].value; + if (nodeValue < minValue) minValue = nodeValue; + if (nodeValue > maxValue) maxValue = nodeValue; + beta = sumValue * sumValue * alpha; + newRatio = Math.max(maxValue / beta, beta / minValue); + if (newRatio > minRatio) { sumValue -= nodeValue; break; } + minRatio = newRatio; + } + + // Position and record the row orientation. + rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); + if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); + else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); + value -= sumValue, i0 = i1; + } + + return rows; +} + +var squarify = (function custom(ratio) { + + function squarify(parent, x0, y0, x1, y1) { + squarifyRatio(ratio, parent, x0, y0, x1, y1); + } + + squarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return squarify; +})(phi); + +var index$1 = function() { + var tile = squarify, + round = false, + dx = 1, + dy = 1, + paddingStack = [0], + paddingInner = constantZero, + paddingTop = constantZero, + paddingRight = constantZero, + paddingBottom = constantZero, + paddingLeft = constantZero; + + function treemap(root) { + root.x0 = + root.y0 = 0; + root.x1 = dx; + root.y1 = dy; + root.eachBefore(positionNode); + paddingStack = [0]; + if (round) root.eachBefore(roundNode); + return root; + } + + function positionNode(node) { + var p = paddingStack[node.depth], + x0 = node.x0 + p, + y0 = node.y0 + p, + x1 = node.x1 - p, + y1 = node.y1 - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + if (node.children) { + p = paddingStack[node.depth + 1] = paddingInner(node) / 2; + x0 += paddingLeft(node) - p; + y0 += paddingTop(node) - p; + x1 -= paddingRight(node) - p; + y1 -= paddingBottom(node) - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + tile(node, x0, y0, x1, y1); + } + } + + treemap.round = function(x) { + return arguments.length ? (round = !!x, treemap) : round; + }; + + treemap.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; + }; + + treemap.tile = function(x) { + return arguments.length ? (tile = required(x), treemap) : tile; + }; + + treemap.padding = function(x) { + return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); + }; + + treemap.paddingInner = function(x) { + return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$6(+x), treemap) : paddingInner; + }; + + treemap.paddingOuter = function(x) { + return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); + }; + + treemap.paddingTop = function(x) { + return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$6(+x), treemap) : paddingTop; + }; + + treemap.paddingRight = function(x) { + return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$6(+x), treemap) : paddingRight; + }; + + treemap.paddingBottom = function(x) { + return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$6(+x), treemap) : paddingBottom; + }; + + treemap.paddingLeft = function(x) { + return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$6(+x), treemap) : paddingLeft; + }; + + return treemap; +}; + +var binary = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + i, n = nodes.length, + sum, sums = new Array(n + 1); + + for (sums[0] = sum = i = 0; i < n; ++i) { + sums[i + 1] = sum += nodes[i].value; + } + + partition(0, n, parent.value, x0, y0, x1, y1); + + function partition(i, j, value, x0, y0, x1, y1) { + if (i >= j - 1) { + var node = nodes[i]; + node.x0 = x0, node.y0 = y0; + node.x1 = x1, node.y1 = y1; + return; + } + + var valueOffset = sums[i], + valueTarget = (value / 2) + valueOffset, + k = i + 1, + hi = j - 1; + + while (k < hi) { + var mid = k + hi >>> 1; + if (sums[mid] < valueTarget) k = mid + 1; + else hi = mid; + } + + var valueLeft = sums[k] - valueOffset, + valueRight = value - valueLeft; + + if ((y1 - y0) > (x1 - x0)) { + var yk = (y0 * valueRight + y1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, x1, yk); + partition(k, j, valueRight, x0, yk, x1, y1); + } else { + var xk = (x0 * valueRight + x1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, xk, y1); + partition(k, j, valueRight, xk, y0, x1, y1); + } + } +}; + +var sliceDice = function(parent, x0, y0, x1, y1) { + (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); +}; + +var resquarify = (function custom(ratio) { + + function resquarify(parent, x0, y0, x1, y1) { + if ((rows = parent._squarify) && (rows.ratio === ratio)) { + var rows, + row, + nodes, + i, + j = -1, + n, + m = rows.length, + value = parent.value; + + while (++j < m) { + row = rows[j], nodes = row.children; + for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; + if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); + else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); + value -= row.value; + } + } else { + parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); + rows.ratio = ratio; + } + } + + resquarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return resquarify; +})(phi); + +var center$1 = function(x, y) { + var nodes; + + if (x == null) x = 0; + if (y == null) y = 0; + + function force() { + var i, + n = nodes.length, + node, + sx = 0, + sy = 0; + + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x, sy += node.y; + } + + for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { + node = nodes[i], node.x -= sx, node.y -= sy; + } + } + + force.initialize = function(_) { + nodes = _; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; +}; + +var constant$7 = function(x) { + return function() { + return x; + }; +}; + +var jiggle = function() { + return (Math.random() - 0.5) * 1e-6; +}; + +function x$1(d) { + return d.x + d.vx; +} + +function y$1(d) { + return d.y + d.vy; +} + +var collide = function(radius) { + var nodes, + radii, + strength = 1, + iterations = 1; + + if (typeof radius !== "function") radius = constant$7(radius == null ? 1 : +radius); + + function force() { + var i, n = nodes.length, + tree, + node, + xi, + yi, + ri, + ri2; + + for (var k = 0; k < iterations; ++k) { + tree = quadtree(nodes, x$1, y$1).visitAfter(prepare); + for (i = 0; i < n; ++i) { + node = nodes[i]; + ri = radii[i], ri2 = ri * ri; + xi = node.x + node.vx; + yi = node.y + node.vy; + tree.visit(apply); + } + } + + function apply(quad, x0, y0, x1, y1) { + var data = quad.data, rj = quad.r, r = ri + rj; + if (data) { + if (data.index > i) { + var x = xi - data.x - data.vx, + y = yi - data.y - data.vy, + l = x * x + y * y; + if (l < r * r) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + l = (r - (l = Math.sqrt(l))) / l * strength; + node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); + node.vy += (y *= l) * r; + data.vx -= x * (r = 1 - r); + data.vy -= y * r; + } + } + return; + } + return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; + } + } + + function prepare(quad) { + if (quad.data) return quad.r = radii[quad.data.index]; + for (var i = quad.r = 0; i < 4; ++i) { + if (quad[i] && quad[i].r > quad.r) { + quad.r = quad[i].r; + } + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + radii = new Array(n); + for (i = 0; i < n; ++i) radii[i] = +radius(nodes[i], i, nodes); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; + }; + + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : radius; + }; + + return force; +}; + +function index$2(d, i) { + return i; +} + +function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) throw new Error("missing: " + nodeId); + return node; +} + +var link = function(links) { + var id = index$2, + strength = defaultStrength, + strengths, + distance = constant$7(30), + distances, + nodes, + count, + bias, + iterations = 1; + + if (links == null) links = []; + + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - distances[i]) / l * alpha * strengths[i]; + x *= l, y *= l; + target.vx -= x * (b = bias[i]); + target.vy -= y * b; + source.vx += x * (b = 1 - b); + source.vy += y * b; + } + } + } + + function initialize() { + if (!nodes) return; + + var i, + n = nodes.length, + m = links.length, + nodeById = map$1(nodes, id), + link; + + for (i = 0, count = new Array(n); i < n; ++i) { + count[i] = 0; + } + + for (i = 0; i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") link.source = find(nodeById, link.source); + if (typeof link.target !== "object") link.target = find(nodeById, link.target); + ++count[link.source.index], ++count[link.target.index]; + } + + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } + + function initializeStrength() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + + function initializeDistance() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + + force.id = function(_) { + return arguments.length ? (id = _, force) : id; + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initializeStrength(), force) : strength; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant$7(+_), initializeDistance(), force) : distance; + }; + + return force; +}; + +function x$2(d) { + return d.x; +} + +function y$2(d) { + return d.y; +} + +var initialRadius = 10; +var initialAngle = Math.PI * (3 - Math.sqrt(5)); + +var simulation = function(nodes) { + var simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = map$1(), + stepper = timer(step), + event = dispatch("tick", "end"); + + if (nodes == null) nodes = []; + + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + + function tick() { + var i, n = nodes.length, node; + + alpha += (alphaTarget - alpha) * alphaDecay; + + forces.each(function(force) { + force(alpha); + }); + + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) node.x += node.vx *= velocityDecay; + else node.x = node.fx, node.vx = 0; + if (node.fy == null) node.y += node.vy *= velocityDecay; + else node.y = node.fy, node.vy = 0; + } + } + + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + + function initializeForce(force) { + if (force.initialize) force.initialize(nodes); + return force; + } + + initializeNodes(); + + return simulation = { + tick: tick, + + restart: function() { + return stepper.restart(step), simulation; + }, + + stop: function() { + return stepper.stop(), simulation; + }, + + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; + }, + + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + + force: function(name, _) { + return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, + + find: function(x, y, radius) { + var i = 0, + n = nodes.length, + dx, + dy, + d2, + node, + closest; + + if (radius == null) radius = Infinity; + else radius *= radius; + + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) closest = node, radius = d2; + } + + return closest; + }, + + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; +}; + +var manyBody = function() { + var nodes, + node, + alpha, + strength = constant$7(-30), + strengths, + distanceMin2 = 1, + distanceMax2 = Infinity, + theta2 = 0.81; + + function force(_) { + var i, n = nodes.length, tree = quadtree(nodes, x$2, y$2).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + for (i = 0; i < n; ++i) strengths[i] = +strength(nodes[i], i, nodes); + } + + function accumulate(quad) { + var strength = 0, q, c, x$$1, y$$1, i; + + // For internal nodes, accumulate forces from child quadrants. + if (quad.length) { + for (x$$1 = y$$1 = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c = q.value)) { + strength += c, x$$1 += c * q.x, y$$1 += c * q.y; + } + } + quad.x = x$$1 / strength; + quad.y = y$$1 / strength; + } + + // For leaf nodes, accumulate forces from coincident quadrants. + else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do strength += strengths[q.data.index]; + while (q = q.next); + } + + quad.value = strength; + } + + function apply(quad, x1, _, x2) { + if (!quad.value) return true; + + var x$$1 = quad.x - node.x, + y$$1 = quad.y - node.y, + w = x2 - x1, + l = x$$1 * x$$1 + y$$1 * y$$1; + + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; + if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + node.vx += x$$1 * quad.value * alpha / l; + node.vy += y$$1 * quad.value * alpha / l; + } + return true; + } + + // Otherwise, process points directly. + else if (quad.length || l >= distanceMax2) return; + + // Limit forces for very close nodes; randomize direction if coincident. + if (quad.data !== node || quad.next) { + if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; + if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + } + + do if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x$$1 * w; + node.vy += y$$1 * w; + } while (quad = quad.next); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; + }; + + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + + return force; +}; + +var x$3 = function(x) { + var strength = constant$7(0.1), + nodes, + strengths, + xz; + + if (typeof x !== "function") x = constant$7(x == null ? 0 : +x); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + xz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; + }; + + force.x = function(_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : x; + }; + + return force; +}; + +var y$3 = function(y) { + var strength = constant$7(0.1), + nodes, + strengths, + yz; + + if (typeof y !== "function") y = constant$7(y == null ? 0 : +y); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + yz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; + }; + + force.y = function(_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : y; + }; + + return force; +}; + +function nopropagation() { + exports.event.stopImmediatePropagation(); +} + +var noevent = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); +}; + +var dragDisable = function(view) { + var root = view.document.documentElement, + selection$$1 = select(view).on("dragstart.drag", noevent, true); + if ("onselectstart" in root) { + selection$$1.on("selectstart.drag", noevent, true); + } else { + root.__noselect = root.style.MozUserSelect; + root.style.MozUserSelect = "none"; + } +}; + +function yesdrag(view, noclick) { + var root = view.document.documentElement, + selection$$1 = select(view).on("dragstart.drag", null); + if (noclick) { + selection$$1.on("click.drag", noevent, true); + setTimeout(function() { selection$$1.on("click.drag", null); }, 0); + } + if ("onselectstart" in root) { + selection$$1.on("selectstart.drag", null); + } else { + root.style.MozUserSelect = root.__noselect; + delete root.__noselect; + } +} + +var constant$8 = function(x) { + return function() { + return x; + }; +}; + +function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) { + this.target = target; + this.type = type; + this.subject = subject; + this.identifier = id; + this.active = active; + this.x = x; + this.y = y; + this.dx = dx; + this.dy = dy; + this._ = dispatch; +} + +DragEvent.prototype.on = function() { + var value = this._.on.apply(this._, arguments); + return value === this._ ? this : value; +}; + +// Ignore right-click, since that should open the context menu. +function defaultFilter() { + return !exports.event.button; +} + +function defaultContainer() { + return this.parentNode; +} + +function defaultSubject(d) { + return d == null ? {x: exports.event.x, y: exports.event.y} : d; +} + +var drag = function() { + var filter = defaultFilter, + container = defaultContainer, + subject = defaultSubject, + gestures = {}, + listeners = dispatch("start", "drag", "end"), + active = 0, + mousemoving, + touchending; + + function drag(selection$$1) { + selection$$1 + .on("mousedown.drag", mousedowned) + .on("touchstart.drag", touchstarted) + .on("touchmove.drag", touchmoved) + .on("touchend.drag touchcancel.drag", touchended) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments); + if (!gesture) return; + select(exports.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); + dragDisable(exports.event.view); + nopropagation(); + mousemoving = false; + gesture("start"); + } + + function mousemoved() { + noevent(); + mousemoving = true; + gestures.mouse("drag"); + } + + function mouseupped() { + select(exports.event.view).on("mousemove.drag mouseup.drag", null); + yesdrag(exports.event.view, mousemoving); + noevent(); + gestures.mouse("end"); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var touches$$1 = exports.event.changedTouches, + c = container.apply(this, arguments), + n = touches$$1.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) { + nopropagation(); + gesture("start"); + } + } + } + + function touchmoved() { + var touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches$$1[i].identifier]) { + noevent(); + gesture("drag"); + } + } + } + + function touchended() { + var touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, gesture; + + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches$$1[i].identifier]) { + nopropagation(); + gesture("end"); + } + } + } + + function beforestart(id, container, point, that, args) { + var p = point(container, id), s, dx, dy, + sublisteners = listeners.copy(); + + if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { + if ((exports.event.subject = s = subject.apply(that, args)) == null) return false; + dx = s.x - p[0] || 0; + dy = s.y - p[1] || 0; + return true; + })) return; + + return function gesture(type) { + var p0 = p, n; + switch (type) { + case "start": gestures[id] = gesture, n = active++; break; + case "end": delete gestures[id], --active; // nobreak + case "drag": p = point(container, id), n = active; break; + } + customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); + }; + } + + drag.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$8(!!_), drag) : filter; + }; + + drag.container = function(_) { + return arguments.length ? (container = typeof _ === "function" ? _ : constant$8(_), drag) : container; + }; + + drag.subject = function(_) { + return arguments.length ? (subject = typeof _ === "function" ? _ : constant$8(_), drag) : subject; + }; + + drag.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? drag : value; + }; + + return drag; +}; + +var constant$9 = function(x) { + return function() { + return x; + }; +}; + +function x$4(d) { + return d[0]; +} + +function y$4(d) { + return d[1]; +} + +function RedBlackTree() { + this._ = null; // root node +} + +function RedBlackNode(node) { + node.U = // parent node + node.C = // color - true for red, false for black + node.L = // left node + node.R = // right node + node.P = // previous node + node.N = null; // next node +} + +RedBlackTree.prototype = { + constructor: RedBlackTree, + + 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 = RedBlackFirst(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) { + RedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + RedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateLeft(this, grandpa); + } + } + 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 = RedBlackFirst(right); + + if (parent) { + if (parent.L === node) parent.L = next; + else parent.R = next; + } else { + this._ = next; + } + + 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 { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + + if (node) node.U = parent; + if (red) return; + if (node && node.C) { node.C = false; return; } + + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateLeft(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; + RedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + RedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateRight(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; + RedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + RedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + + if (node) node.C = false; + } +}; + +function RedBlackRotateLeft(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 RedBlackRotateRight(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 RedBlackFirst(node) { + while (node.L) node = node.L; + return node; +} + +function createEdge(left, right, v0, v1) { + var edge = [null, null], + index = edges.push(edge) - 1; + edge.left = left; + edge.right = right; + if (v0) setEdgeEnd(edge, left, right, v0); + if (v1) setEdgeEnd(edge, right, left, v1); + cells[left.index].halfedges.push(index); + cells[right.index].halfedges.push(index); + return edge; +} + +function createBorderEdge(left, v0, v1) { + var edge = [v0, v1]; + edge.left = left; + return edge; +} + +function setEdgeEnd(edge, left, right, vertex) { + if (!edge[0] && !edge[1]) { + edge[0] = vertex; + edge.left = left; + edge.right = right; + } else if (edge.left === right) { + edge[1] = vertex; + } else { + edge[0] = vertex; + } +} + +// Liang–Barsky line clipping. +function clipEdge(edge, x0, y0, x1, y1) { + var a = edge[0], + b = edge[1], + ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + 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) && !(t1 < 1)) return true; // TODO Better check? + + if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy]; + if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy]; + return true; +} + +function connectEdge(edge, x0, y0, x1, y1) { + var v1 = edge[1]; + if (v1) return true; + + var v0 = edge[0], + left = edge.left, + right = edge.right, + lx = left[0], + ly = left[1], + rx = right[0], + ry = right[1], + fx = (lx + rx) / 2, + fy = (ly + ry) / 2, + fm, + fb; + + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!v0) v0 = [fx, y0]; + else if (v0[1] >= y1) return; + v1 = [fx, y1]; + } else { + if (!v0) v0 = [fx, y1]; + else if (v0[1] < y0) return; + v1 = [fx, y0]; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!v0) v0 = [(y0 - fb) / fm, y0]; + else if (v0[1] >= y1) return; + v1 = [(y1 - fb) / fm, y1]; + } else { + if (!v0) v0 = [(y1 - fb) / fm, y1]; + else if (v0[1] < y0) return; + v1 = [(y0 - fb) / fm, y0]; + } + } else { + if (ly < ry) { + if (!v0) v0 = [x0, fm * x0 + fb]; + else if (v0[0] >= x1) return; + v1 = [x1, fm * x1 + fb]; + } else { + if (!v0) v0 = [x1, fm * x1 + fb]; + else if (v0[0] < x0) return; + v1 = [x0, fm * x0 + fb]; + } + } + } + + edge[0] = v0; + edge[1] = v1; + return true; +} + +function clipEdges(x0, y0, x1, y1) { + var i = edges.length, + edge; + + while (i--) { + if (!connectEdge(edge = edges[i], x0, y0, x1, y1) + || !clipEdge(edge, x0, y0, x1, y1) + || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$3 + || Math.abs(edge[0][1] - edge[1][1]) > epsilon$3)) { + delete edges[i]; + } + } +} + +function createCell(site) { + return cells[site.index] = { + site: site, + halfedges: [] + }; +} + +function cellHalfedgeAngle(cell, edge) { + var site = cell.site, + va = edge.left, + vb = edge.right; + if (site === vb) vb = va, va = site; + if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]); + if (site === va) va = edge[1], vb = edge[0]; + else va = edge[0], vb = edge[1]; + return Math.atan2(va[0] - vb[0], vb[1] - va[1]); +} + +function cellHalfedgeStart(cell, edge) { + return edge[+(edge.left !== cell.site)]; +} + +function cellHalfedgeEnd(cell, edge) { + return edge[+(edge.left === cell.site)]; +} + +function sortCellHalfedges() { + for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { + if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { + var index = new Array(m), + array = new Array(m); + for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]); + index.sort(function(i, j) { return array[j] - array[i]; }); + for (j = 0; j < m; ++j) array[j] = halfedges[index[j]]; + for (j = 0; j < m; ++j) halfedges[j] = array[j]; + } + } +} + +function clipCells(x0, y0, x1, y1) { + var nCells = cells.length, + iCell, + cell, + site, + iHalfedge, + halfedges, + nHalfedges, + start, + startX, + startY, + end, + endX, + endY, + cover = true; + + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + halfedges = cell.halfedges; + iHalfedge = halfedges.length; + + // Remove any dangling clipped edges. + while (iHalfedge--) { + if (!edges[halfedges[iHalfedge]]) { + halfedges.splice(iHalfedge, 1); + } + } + + // Insert any border edges as necessary. + iHalfedge = 0, nHalfedges = halfedges.length; + while (iHalfedge < nHalfedges) { + end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1]; + start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; + if (Math.abs(endX - startX) > epsilon$3 || Math.abs(endY - startY) > epsilon$3) { + halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, + Math.abs(endX - x0) < epsilon$3 && y1 - endY > epsilon$3 ? [x0, Math.abs(startX - x0) < epsilon$3 ? startY : y1] + : Math.abs(endY - y1) < epsilon$3 && x1 - endX > epsilon$3 ? [Math.abs(startY - y1) < epsilon$3 ? startX : x1, y1] + : Math.abs(endX - x1) < epsilon$3 && endY - y0 > epsilon$3 ? [x1, Math.abs(startX - x1) < epsilon$3 ? startY : y0] + : Math.abs(endY - y0) < epsilon$3 && endX - x0 > epsilon$3 ? [Math.abs(startY - y0) < epsilon$3 ? startX : x0, y0] + : null)) - 1); + ++nHalfedges; + } + } + + if (nHalfedges) cover = false; + } + } + + // If there weren’t any edges, have the closest site cover the extent. + // It doesn’t matter which corner of the extent we measure! + if (cover) { + var dx, dy, d2, dc = Infinity; + + for (iCell = 0, cover = null; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + dx = site[0] - x0; + dy = site[1] - y0; + d2 = dx * dx + dy * dy; + if (d2 < dc) dc = d2, cover = cell; + } + } + + if (cover) { + var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; + cover.halfedges.push( + edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, + edges.push(createBorderEdge(site, v01, v11)) - 1, + edges.push(createBorderEdge(site, v11, v10)) - 1, + edges.push(createBorderEdge(site, v10, v00)) - 1 + ); + } + } + + // Lastly delete any cells with no edges; these were entirely clipped. + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + if (!cell.halfedges.length) { + delete cells[iCell]; + } + } + } +} + +var circlePool = []; + +var firstCircle; + +function Circle() { + RedBlackNode(this); + this.x = + this.y = + this.arc = + this.site = + this.cy = null; +} + +function attachCircle(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[0], + by = cSite[1], + ax = lSite[0] - bx, + ay = lSite[1] - by, + cx = rSite[0] - bx, + cy = rSite[1] - by; + + var d = 2 * (ax * cy - ay * cx); + if (d >= -epsilon2$1) return; + + var ha = ax * ax + ay * ay, + hc = cx * cx + cy * cy, + x = (cy * ha - ay * hc) / d, + y = (ax * hc - cx * ha) / d; + + var circle = circlePool.pop() || new Circle; + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom + + arc.circle = circle; + + var before = null, + node = circles._; + + 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; } + } + } + + circles.insert(before, circle); + if (!before) firstCircle = circle; +} + +function detachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) firstCircle = circle.N; + circles.remove(circle); + circlePool.push(circle); + RedBlackNode(circle); + arc.circle = null; + } +} + +var beachPool = []; + +function Beach() { + RedBlackNode(this); + this.edge = + this.site = + this.circle = null; +} + +function createBeach(site) { + var beach = beachPool.pop() || new Beach; + beach.site = site; + return beach; +} + +function detachBeach(beach) { + detachCircle(beach); + beaches.remove(beach); + beachPool.push(beach); + RedBlackNode(beach); +} + +function removeBeach(beach) { + var circle = beach.circle, + x = circle.x, + y = circle.cy, + vertex = [x, y], + previous = beach.P, + next = beach.N, + disappearing = [beach]; + + detachBeach(beach); + + var lArc = previous; + while (lArc.circle + && Math.abs(x - lArc.circle.x) < epsilon$3 + && Math.abs(y - lArc.circle.cy) < epsilon$3) { + previous = lArc.P; + disappearing.unshift(lArc); + detachBeach(lArc); + lArc = previous; + } + + disappearing.unshift(lArc); + detachCircle(lArc); + + var rArc = next; + while (rArc.circle + && Math.abs(x - rArc.circle.x) < epsilon$3 + && Math.abs(y - rArc.circle.cy) < epsilon$3) { + next = rArc.N; + disappearing.push(rArc); + detachBeach(rArc); + rArc = next; + } + + disappearing.push(rArc); + detachCircle(rArc); + + var nArcs = disappearing.length, + iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = createEdge(lArc.site, rArc.site, null, vertex); + + attachCircle(lArc); + attachCircle(rArc); +} + +function addBeach(site) { + var x = site[0], + directrix = site[1], + lArc, + rArc, + dxl, + dxr, + node = beaches._; + + while (node) { + dxl = leftBreakPoint(node, directrix) - x; + if (dxl > epsilon$3) node = node.L; else { + dxr = x - rightBreakPoint(node, directrix); + if (dxr > epsilon$3) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -epsilon$3) { + lArc = node.P; + rArc = node; + } else if (dxr > -epsilon$3) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + + createCell(site); + var newArc = createBeach(site); + beaches.insert(lArc, newArc); + + if (!lArc && !rArc) return; + + if (lArc === rArc) { + detachCircle(lArc); + rArc = createBeach(lArc.site); + beaches.insert(newArc, rArc); + newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site); + attachCircle(lArc); + attachCircle(rArc); + return; + } + + if (!rArc) { // && lArc + newArc.edge = createEdge(lArc.site, newArc.site); + return; + } + + // else lArc !== rArc + detachCircle(lArc); + detachCircle(rArc); + + var lSite = lArc.site, + ax = lSite[0], + ay = lSite[1], + bx = site[0] - ax, + by = site[1] - ay, + rSite = rArc.site, + cx = rSite[0] - ax, + cy = rSite[1] - ay, + d = 2 * (bx * cy - by * cx), + hb = bx * bx + by * by, + hc = cx * cx + cy * cy, + vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay]; + + setEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = createEdge(lSite, site, null, vertex); + rArc.edge = createEdge(site, rSite, null, vertex); + attachCircle(lArc); + attachCircle(rArc); +} + +function leftBreakPoint(arc, directrix) { + var site = arc.site, + rfocx = site[0], + rfocy = site[1], + pby2 = rfocy - directrix; + + if (!pby2) return rfocx; + + var lArc = arc.P; + if (!lArc) return -Infinity; + + site = lArc.site; + var lfocx = site[0], + lfocy = site[1], + 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 rightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return leftBreakPoint(rArc, directrix); + var site = arc.site; + return site[1] === directrix ? site[0] : Infinity; +} + +var epsilon$3 = 1e-6; +var epsilon2$1 = 1e-12; +var beaches; +var cells; +var circles; +var edges; + +function triangleArea(a, b, c) { + return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); +} + +function lexicographic(a, b) { + return b[1] - a[1] + || b[0] - a[0]; +} + +function Diagram(sites, extent) { + var site = sites.sort(lexicographic).pop(), + x, + y, + circle; + + edges = []; + cells = new Array(sites.length); + beaches = new RedBlackTree; + circles = new RedBlackTree; + + while (true) { + circle = firstCircle; + if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { + if (site[0] !== x || site[1] !== y) { + addBeach(site); + x = site[0], y = site[1]; + } + site = sites.pop(); + } else if (circle) { + removeBeach(circle.arc); + } else { + break; + } + } + + sortCellHalfedges(); + + if (extent) { + var x0 = +extent[0][0], + y0 = +extent[0][1], + x1 = +extent[1][0], + y1 = +extent[1][1]; + clipEdges(x0, y0, x1, y1); + clipCells(x0, y0, x1, y1); + } + + this.edges = edges; + this.cells = cells; + + beaches = + circles = + edges = + cells = null; +} + +Diagram.prototype = { + constructor: Diagram, + + polygons: function() { + var edges = this.edges; + + return this.cells.map(function(cell) { + var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); }); + polygon.data = cell.site.data; + return polygon; + }); + }, + + triangles: function() { + var triangles = [], + edges = this.edges; + + this.cells.forEach(function(cell, i) { + var site = cell.site, + halfedges = cell.halfedges, + j = -1, + m = halfedges.length, + s0, + e1 = edges[halfedges[m - 1]], + s1 = e1.left === site ? e1.right : e1.left; + + while (++j < m) { + s0 = s1; + e1 = edges[halfedges[j]]; + s1 = e1.left === site ? e1.right : e1.left; + if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { + triangles.push([site.data, s0.data, s1.data]); + } + } + }); + + return triangles; + }, + + links: function() { + return this.edges.filter(function(edge) { + return edge.right; + }).map(function(edge) { + return { + source: edge.left.data, + target: edge.right.data + }; + }); + }, + + find: function(x, y, radius) { + var that = this, + i0, i1 = that._found || 0, + cell = that.cells[i1] || that.cells[i1 = 0], + dx = x - cell.site[0], + dy = y - cell.site[1], + d2 = dx * dx + dy * dy; + + do { + cell = that.cells[i0 = i1], i1 = null; + cell.halfedges.forEach(function(e) { + var edge = that.edges[e], v = edge.left; + if ((v === cell.site || !v) && !(v = edge.right)) return; + var vx = x - v[0], + vy = y - v[1], + v2 = vx * vx + vy * vy; + if (v2 < d2) d2 = v2, i1 = v.index; + }); + } while (i1 !== null); + + that._found = i0; + + return radius == null || d2 <= radius * radius ? cell.site : null; + } +}; + +var voronoi = function() { + var x$$1 = x$4, + y$$1 = y$4, + extent = null; + + function voronoi(data) { + return new Diagram(data.map(function(d, i) { + var s = [Math.round(x$$1(d, i, data) / epsilon$3) * epsilon$3, Math.round(y$$1(d, i, data) / epsilon$3) * epsilon$3]; + s.index = i; + s.data = d; + return s; + }), extent); + } + + voronoi.polygons = function(data) { + return voronoi(data).polygons(); + }; + + voronoi.links = function(data) { + return voronoi(data).links(); + }; + + voronoi.triangles = function(data) { + return voronoi(data).triangles(); + }; + + voronoi.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : x$$1; + }; + + voronoi.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : y$$1; + }; + + voronoi.extent = function(_) { + return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]]; + }; + + voronoi.size = function(_) { + return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]]; + }; + + return voronoi; +}; + +var constant$10 = function(x) { + return function() { + return x; + }; +}; + +function ZoomEvent(target, type, transform) { + this.target = target; + this.type = type; + this.transform = transform; +} + +function Transform(k, x, y) { + this.k = k; + this.x = x; + this.y = y; +} + +Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x, y) { + return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x) { + return x * this.k + this.x; + }, + applyY: function(y) { + return y * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x) { + return (x - this.x) / this.k; + }, + invertY: function(y) { + return (y - this.y) / this.k; + }, + rescaleX: function(x) { + return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); + }, + rescaleY: function(y) { + return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } +}; + +var identity$6 = new Transform(1, 0, 0); + +transform.prototype = Transform.prototype; + +function transform(node) { + return node.__zoom || identity$6; +} + +function nopropagation$1() { + exports.event.stopImmediatePropagation(); +} + +var noevent$1 = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); +}; + +// Ignore right-click, since that should open the context menu. +function defaultFilter$1() { + return !exports.event.button; +} + +function defaultExtent() { + var e = this, w, h; + if (e instanceof SVGElement) { + e = e.ownerSVGElement || e; + w = e.width.baseVal.value; + h = e.height.baseVal.value; + } else { + w = e.clientWidth; + h = e.clientHeight; + } + return [[0, 0], [w, h]]; +} + +function defaultTransform() { + return this.__zoom || identity$6; +} + +var zoom = function() { + var filter = defaultFilter$1, + extent = defaultExtent, + k0 = 0, + k1 = Infinity, + x0 = -k1, + x1 = k1, + y0 = x0, + y1 = x1, + duration = 250, + gestures = [], + listeners = dispatch("start", "zoom", "end"), + touchstarting, + touchending, + touchDelay = 500, + wheelDelay = 150; + + function zoom(selection$$1) { + selection$$1 + .on("wheel.zoom", wheeled) + .on("mousedown.zoom", mousedowned) + .on("dblclick.zoom", dblclicked) + .on("touchstart.zoom", touchstarted) + .on("touchmove.zoom", touchmoved) + .on("touchend.zoom touchcancel.zoom", touchended) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") + .property("__zoom", defaultTransform); + } + + zoom.transform = function(collection, transform) { + var selection$$1 = collection.selection ? collection.selection() : collection; + selection$$1.property("__zoom", defaultTransform); + if (collection !== selection$$1) { + schedule(collection, transform); + } else { + selection$$1.interrupt().each(function() { + gesture(this, arguments) + .start() + .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform) + .end(); + }); + } + }; + + zoom.scaleBy = function(selection$$1, k) { + zoom.scaleTo(selection$$1, function() { + var k0 = this.__zoom.k, + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return k0 * k1; + }); + }; + + zoom.scaleTo = function(selection$$1, k) { + zoom.transform(selection$$1, function() { + var e = extent.apply(this, arguments), + t0 = this.__zoom, + p0 = centroid(e), + p1 = t0.invert(p0), + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return constrain(translate(scale(t0, k1), p0, p1), e); + }); + }; + + zoom.translateBy = function(selection$$1, x, y) { + zoom.transform(selection$$1, function() { + return constrain(this.__zoom.translate( + typeof x === "function" ? x.apply(this, arguments) : x, + typeof y === "function" ? y.apply(this, arguments) : y + ), extent.apply(this, arguments)); + }); + }; + + function scale(transform, k) { + k = Math.max(k0, Math.min(k1, k)); + return k === transform.k ? transform : new Transform(k, transform.x, transform.y); + } + + function translate(transform, p0, p1) { + var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k; + return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y); + } + + function constrain(transform, extent) { + var dx = Math.min(0, transform.invertX(extent[0][0]) - x0) || Math.max(0, transform.invertX(extent[1][0]) - x1), + dy = Math.min(0, transform.invertY(extent[0][1]) - y0) || Math.max(0, transform.invertY(extent[1][1]) - y1); + return dx || dy ? transform.translate(dx, dy) : transform; + } + + function centroid(extent) { + return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; + } + + function schedule(transition$$1, transform, center) { + transition$$1 + .on("start.zoom", function() { gesture(this, arguments).start(); }) + .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); }) + .tween("zoom", function() { + var that = this, + args = arguments, + g = gesture(that, args), + e = extent.apply(that, args), + p = center || centroid(e), + w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), + a = that.__zoom, + b = typeof transform === "function" ? transform.apply(that, args) : transform, + i = interpolateZoom(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); + return function(t) { + if (t === 1) t = b; // Avoid rounding error on end. + else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } + g.zoom(null, t); + }; + }); + } + + function gesture(that, args) { + for (var i = 0, n = gestures.length, g; i < n; ++i) { + if ((g = gestures[i]).that === that) { + return g; + } + } + return new Gesture(that, args); + } + + function Gesture(that, args) { + this.that = that; + this.args = args; + this.index = -1; + this.active = 0; + this.extent = extent.apply(that, args); + } + + Gesture.prototype = { + start: function() { + if (++this.active === 1) { + this.index = gestures.push(this) - 1; + this.emit("start"); + } + return this; + }, + zoom: function(key, transform) { + if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]); + if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]); + if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]); + this.that.__zoom = transform; + this.emit("zoom"); + return this; + }, + end: function() { + if (--this.active === 0) { + gestures.splice(this.index, 1); + this.index = -1; + this.emit("end"); + } + return this; + }, + emit: function(type) { + customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function wheeled() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + t = this.__zoom, + k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -exports.event.deltaY * (exports.event.deltaMode ? 120 : 1) / 500))), + p = mouse(this); + + // If the mouse is in the same location as before, reuse it. + // If there were recent wheel events, reset the wheel idle timeout. + if (g.wheel) { + if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { + g.mouse[1] = t.invert(g.mouse[0] = p); + } + clearTimeout(g.wheel); + } + + // If this wheel event won’t trigger a transform change, ignore it. + else if (t.k === k) return; + + // Otherwise, capture the mouse point and location at the start. + else { + g.mouse = [p, t.invert(p)]; + interrupt(this); + g.start(); + } + + noevent$1(); + g.wheel = setTimeout(wheelidled, wheelDelay); + g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent)); + + function wheelidled() { + g.wheel = null; + g.end(); + } + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + v = select(exports.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), + p = mouse(this); + + dragDisable(exports.event.view); + nopropagation$1(); + g.mouse = [p, this.__zoom.invert(p)]; + interrupt(this); + g.start(); + + function mousemoved() { + noevent$1(); + g.moved = true; + g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent)); + } + + function mouseupped() { + v.on("mousemove.zoom mouseup.zoom", null); + yesdrag(exports.event.view, g.moved); + noevent$1(); + g.end(); + } + } + + function dblclicked() { + if (!filter.apply(this, arguments)) return; + var t0 = this.__zoom, + p0 = mouse(this), + p1 = t0.invert(p0), + k1 = t0.k * (exports.event.shiftKey ? 0.5 : 2), + t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments)); + + noevent$1(); + if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0); + else select(this).call(zoom.transform, t1); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, t, p; + + nopropagation$1(); + for (i = 0; i < n; ++i) { + t = touches$$1[i], p = touch(this, touches$$1, t.identifier); + p = [p, this.__zoom.invert(p), t.identifier]; + if (!g.touch0) g.touch0 = p; + else if (!g.touch1) g.touch1 = p; + } + if (touchstarting) { + touchstarting = clearTimeout(touchstarting); + if (!g.touch1) return g.end(), dblclicked.apply(this, arguments); + } + if (exports.event.touches.length === n) { + touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); + interrupt(this); + g.start(); + } + } + + function touchmoved() { + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, t, p, l; + + noevent$1(); + if (touchstarting) touchstarting = clearTimeout(touchstarting); + for (i = 0; i < n; ++i) { + t = touches$$1[i], p = touch(this, touches$$1, t.identifier); + if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; + else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; + } + t = g.that.__zoom; + if (g.touch1) { + var p0 = g.touch0[0], l0 = g.touch0[1], + p1 = g.touch1[0], l1 = g.touch1[1], + dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, + dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; + t = scale(t, Math.sqrt(dp / dl)); + p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; + l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; + } + else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; + else return; + g.zoom("touch", constrain(translate(t, p, l), g.extent)); + } + + function touchended() { + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, t; + + nopropagation$1(); + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, touchDelay); + for (i = 0; i < n; ++i) { + t = touches$$1[i]; + if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; + else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; + } + if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; + if (!g.touch0) g.end(); + } + + zoom.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$10(!!_), zoom) : filter; + }; + + zoom.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$10([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; + }; + + zoom.scaleExtent = function(_) { + return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1]; + }; + + zoom.translateExtent = function(_) { + return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]]; + }; + + zoom.duration = function(_) { + return arguments.length ? (duration = +_, zoom) : duration; + }; + + zoom.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? zoom : value; + }; + + return zoom; +}; + +var constant$11 = function(x) { + return function() { + return x; + }; +}; + +var BrushEvent = function(target, type, selection) { + this.target = target; + this.type = type; + this.selection = selection; +}; + +function nopropagation$2() { + exports.event.stopImmediatePropagation(); +} + +var noevent$2 = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); +}; + +var MODE_DRAG = {name: "drag"}; +var MODE_SPACE = {name: "space"}; +var MODE_HANDLE = {name: "handle"}; +var MODE_CENTER = {name: "center"}; + +var X = { + name: "x", + handles: ["e", "w"].map(type$1), + input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; }, + output: function(xy) { return xy && [xy[0][0], xy[1][0]]; } +}; + +var Y = { + name: "y", + handles: ["n", "s"].map(type$1), + input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; }, + output: function(xy) { return xy && [xy[0][1], xy[1][1]]; } +}; + +var XY = { + name: "xy", + handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$1), + input: function(xy) { return xy; }, + output: function(xy) { return xy; } +}; + +var cursors = { + overlay: "crosshair", + selection: "move", + 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 flipX = { + e: "w", + w: "e", + nw: "ne", + ne: "nw", + se: "sw", + sw: "se" +}; + +var flipY = { + n: "s", + s: "n", + nw: "sw", + ne: "se", + se: "ne", + sw: "nw" +}; + +var signsX = { + overlay: +1, + selection: +1, + n: null, + e: +1, + s: null, + w: -1, + nw: -1, + ne: +1, + se: +1, + sw: -1 +}; + +var signsY = { + overlay: +1, + selection: +1, + n: -1, + e: null, + s: +1, + w: null, + nw: -1, + ne: -1, + se: +1, + sw: +1 +}; + +function type$1(t) { + return {type: t}; +} + +// Ignore right-click, since that should open the context menu. +function defaultFilter$2() { + return !exports.event.button; +} + +function defaultExtent$1() { + var svg = this.ownerSVGElement || this; + return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; +} + +// Like d3.local, but with the name “__brush” rather than auto-generated. +function local$1(node) { + while (!node.__brush) if (!(node = node.parentNode)) return; + return node.__brush; +} + +function empty$1(extent) { + return extent[0][0] === extent[1][0] + || extent[0][1] === extent[1][1]; +} + +function brushSelection(node) { + var state = node.__brush; + return state ? state.dim.output(state.selection) : null; +} + +function brushX() { + return brush$1(X); +} + +function brushY() { + return brush$1(Y); +} + +var brush = function() { + return brush$1(XY); +}; + +function brush$1(dim) { + var extent = defaultExtent$1, + filter = defaultFilter$2, + listeners = dispatch(brush, "start", "brush", "end"), + handleSize = 6, + touchending; + + function brush(group) { + var overlay = group + .property("__brush", initialize) + .selectAll(".overlay") + .data([type$1("overlay")]); + + overlay.enter().append("rect") + .attr("class", "overlay") + .attr("pointer-events", "all") + .attr("cursor", cursors.overlay) + .merge(overlay) + .each(function() { + var extent = local$1(this).extent; + select(this) + .attr("x", extent[0][0]) + .attr("y", extent[0][1]) + .attr("width", extent[1][0] - extent[0][0]) + .attr("height", extent[1][1] - extent[0][1]); + }); + + group.selectAll(".selection") + .data([type$1("selection")]) + .enter().append("rect") + .attr("class", "selection") + .attr("cursor", cursors.selection) + .attr("fill", "#777") + .attr("fill-opacity", 0.3) + .attr("stroke", "#fff") + .attr("shape-rendering", "crispEdges"); + + var handle = group.selectAll(".handle") + .data(dim.handles, function(d) { return d.type; }); + + handle.exit().remove(); + + handle.enter().append("rect") + .attr("class", function(d) { return "handle handle--" + d.type; }) + .attr("cursor", function(d) { return cursors[d.type]; }); + + group + .each(redraw) + .attr("fill", "none") + .attr("pointer-events", "all") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") + .on("mousedown.brush touchstart.brush", started); + } + + brush.move = function(group, selection$$1) { + if (group.selection) { + group + .on("start.brush", function() { emitter(this, arguments).beforestart().start(); }) + .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); }) + .tween("brush", function() { + var that = this, + state = that.__brush, + emit = emitter(that, arguments), + selection0 = state.selection, + selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent), + i = interpolate(selection0, selection1); + + function tween(t) { + state.selection = t === 1 && empty$1(selection1) ? null : i(t); + redraw.call(that); + emit.brush(); + } + + return selection0 && selection1 ? tween : tween(1); + }); + } else { + group + .each(function() { + var that = this, + args = arguments, + state = that.__brush, + selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent), + emit = emitter(that, args).beforestart(); + + interrupt(that); + state.selection = selection1 == null || empty$1(selection1) ? null : selection1; + redraw.call(that); + emit.start().brush().end(); + }); + } + }; + + function redraw() { + var group = select(this), + selection$$1 = local$1(this).selection; + + if (selection$$1) { + group.selectAll(".selection") + .style("display", null) + .attr("x", selection$$1[0][0]) + .attr("y", selection$$1[0][1]) + .attr("width", selection$$1[1][0] - selection$$1[0][0]) + .attr("height", selection$$1[1][1] - selection$$1[0][1]); + + group.selectAll(".handle") + .style("display", null) + .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; }) + .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; }) + .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; }) + .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; }); + } + + else { + group.selectAll(".selection,.handle") + .style("display", "none") + .attr("x", null) + .attr("y", null) + .attr("width", null) + .attr("height", null); + } + } + + function emitter(that, args) { + return that.__brush.emitter || new Emitter(that, args); + } + + function Emitter(that, args) { + this.that = that; + this.args = args; + this.state = that.__brush; + this.active = 0; + } + + Emitter.prototype = { + beforestart: function() { + if (++this.active === 1) this.state.emitter = this, this.starting = true; + return this; + }, + start: function() { + if (this.starting) this.starting = false, this.emit("start"); + return this; + }, + brush: function() { + this.emit("brush"); + return this; + }, + end: function() { + if (--this.active === 0) delete this.state.emitter, this.emit("end"); + return this; + }, + emit: function(type) { + customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function started() { + if (exports.event.touches) { if (exports.event.changedTouches.length < exports.event.touches.length) return noevent$2(); } + else if (touchending) return; + if (!filter.apply(this, arguments)) return; + + var that = this, + type = exports.event.target.__data__.type, + mode = (exports.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (exports.event.altKey ? MODE_CENTER : MODE_HANDLE), + signX = dim === Y ? null : signsX[type], + signY = dim === X ? null : signsY[type], + state = local$1(that), + extent = state.extent, + selection$$1 = state.selection, + W = extent[0][0], w0, w1, + N = extent[0][1], n0, n1, + E = extent[1][0], e0, e1, + S = extent[1][1], s0, s1, + dx, + dy, + moving, + shifting = signX && signY && exports.event.shiftKey, + lockX, + lockY, + point0 = mouse(that), + point = point0, + emit = emitter(that, arguments).beforestart(); + + if (type === "overlay") { + state.selection = selection$$1 = [ + [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], + [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] + ]; + } else { + w0 = selection$$1[0][0]; + n0 = selection$$1[0][1]; + e0 = selection$$1[1][0]; + s0 = selection$$1[1][1]; + } + + w1 = w0; + n1 = n0; + e1 = e0; + s1 = s0; + + var group = select(that) + .attr("pointer-events", "none"); + + var overlay = group.selectAll(".overlay") + .attr("cursor", cursors[type]); + + if (exports.event.touches) { + group + .on("touchmove.brush", moved, true) + .on("touchend.brush touchcancel.brush", ended, true); + } else { + var view = select(exports.event.view) + .on("keydown.brush", keydowned, true) + .on("keyup.brush", keyupped, true) + .on("mousemove.brush", moved, true) + .on("mouseup.brush", ended, true); + + dragDisable(exports.event.view); + } + + nopropagation$2(); + interrupt(that); + redraw.call(that); + emit.start(); + + function moved() { + var point1 = mouse(that); + if (shifting && !lockX && !lockY) { + if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true; + else lockX = true; + } + point = point1; + moving = true; + noevent$2(); + move(); + } + + function move() { + var t; + + dx = point[0] - point0[0]; + dy = point[1] - point0[1]; + + switch (mode) { + case MODE_SPACE: + case MODE_DRAG: { + if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; + if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; + break; + } + case MODE_HANDLE: { + if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; + else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; + if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; + else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; + break; + } + case MODE_CENTER: { + if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); + if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); + break; + } + } + + if (e1 < w1) { + signX *= -1; + t = w0, w0 = e0, e0 = t; + t = w1, w1 = e1, e1 = t; + if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]); + } + + if (s1 < n1) { + signY *= -1; + t = n0, n0 = s0, s0 = t; + t = n1, n1 = s1, s1 = t; + if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]); + } + + if (state.selection) selection$$1 = state.selection; // May be set by brush.move! + if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0]; + if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1]; + + if (selection$$1[0][0] !== w1 + || selection$$1[0][1] !== n1 + || selection$$1[1][0] !== e1 + || selection$$1[1][1] !== s1) { + state.selection = [[w1, n1], [e1, s1]]; + redraw.call(that); + emit.brush(); + } + } + + function ended() { + nopropagation$2(); + if (exports.event.touches) { + if (exports.event.touches.length) return; + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + group.on("touchmove.brush touchend.brush touchcancel.brush", null); + } else { + yesdrag(exports.event.view, moving); + view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); + } + group.attr("pointer-events", "all"); + overlay.attr("cursor", cursors.overlay); + if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)! + if (empty$1(selection$$1)) state.selection = null, redraw.call(that); + emit.end(); + } + + function keydowned() { + switch (exports.event.keyCode) { + case 16: { // SHIFT + shifting = signX && signY; + break; + } + case 18: { // ALT + if (mode === MODE_HANDLE) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + move(); + } + break; + } + case 32: { // SPACE; takes priority over ALT + if (mode === MODE_HANDLE || mode === MODE_CENTER) { + if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx; + if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy; + mode = MODE_SPACE; + overlay.attr("cursor", cursors.selection); + move(); + } + break; + } + default: return; + } + noevent$2(); + } + + function keyupped() { + switch (exports.event.keyCode) { + case 16: { // SHIFT + if (shifting) { + lockX = lockY = shifting = false; + move(); + } + break; + } + case 18: { // ALT + if (mode === MODE_CENTER) { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + move(); + } + break; + } + case 32: { // SPACE + if (mode === MODE_SPACE) { + if (exports.event.altKey) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + } else { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + } + overlay.attr("cursor", cursors[type]); + move(); + } + break; + } + default: return; + } + noevent$2(); + } + } + + function initialize() { + var state = this.__brush || {selection: null}; + state.extent = extent.apply(this, arguments); + state.dim = dim; + return state; + } + + brush.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$11([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent; + }; + + brush.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$11(!!_), brush) : filter; + }; + + brush.handleSize = function(_) { + return arguments.length ? (handleSize = +_, brush) : handleSize; + }; + + brush.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? brush : value; + }; + + return brush; +} + +var cos = Math.cos; +var sin = Math.sin; +var pi$3 = Math.PI; +var halfPi$2 = pi$3 / 2; +var tau$3 = pi$3 * 2; +var max$1 = Math.max; + +function compareValue(compare) { + return function(a, b) { + return compare( + a.source.value + a.target.value, + b.source.value + b.target.value + ); + }; +} + +var chord = function() { + var padAngle = 0, + sortGroups = null, + sortSubgroups = null, + sortChords = null; + + function chord(matrix) { + var n = matrix.length, + groupSums = [], + groupIndex = range(n), + subgroupIndex = [], + chords = [], + groups = chords.groups = new Array(n), + subgroups = new Array(n * n), + k, + x, + x0, + dx, + i, + j; + + // Compute the sum. + k = 0, i = -1; while (++i < n) { + x = 0, j = -1; while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(range(n)); + k += x; + } + + // Sort groups… + if (sortGroups) groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + + // Sort subgroups… + if (sortSubgroups) subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + + // Convert the sum to scaling factor for [0, 2pi]. + // TODO Allow start and end angle to be specified? + // TODO Allow padding to be specified as percentage? + k = max$1(0, tau$3 - padAngle * n) / k; + dx = k ? padAngle : tau$3 / n; + + // Compute the start and end angle for each group and subgroup. + // Note: Opera has a bug reordering object literal properties! + 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[dj * n + di] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += dx; + } + + // Generate chords for each (non-empty) subgroup-subgroup link. + i = -1; while (++i < n) { + j = i - 1; while (++j < n) { + var source = subgroups[j * n + i], + target = subgroups[i * n + j]; + if (source.value || target.value) { + chords.push(source.value < target.value + ? {source: target, target: source} + : {source: source, target: target}); + } + } + } + + return sortChords ? chords.sort(sortChords) : chords; + } + + chord.padAngle = function(_) { + return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle; + }; + + chord.sortGroups = function(_) { + return arguments.length ? (sortGroups = _, chord) : sortGroups; + }; + + chord.sortSubgroups = function(_) { + return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; + }; + + chord.sortChords = function(_) { + return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; + }; + + return chord; +}; + +var slice$5 = Array.prototype.slice; + +var constant$12 = function(x) { + return function() { + return x; + }; +}; + +function defaultSource(d) { + return d.source; +} + +function defaultTarget(d) { + return d.target; +} + +function defaultRadius$1(d) { + return d.radius; +} + +function defaultStartAngle(d) { + return d.startAngle; +} + +function defaultEndAngle(d) { + return d.endAngle; +} + +var ribbon = function() { + var source = defaultSource, + target = defaultTarget, + radius = defaultRadius$1, + startAngle = defaultStartAngle, + endAngle = defaultEndAngle, + context = null; + + function ribbon() { + var buffer, + argv = slice$5.call(arguments), + s = source.apply(this, argv), + t = target.apply(this, argv), + sr = +radius.apply(this, (argv[0] = s, argv)), + sa0 = startAngle.apply(this, argv) - halfPi$2, + sa1 = endAngle.apply(this, argv) - halfPi$2, + sx0 = sr * cos(sa0), + sy0 = sr * sin(sa0), + tr = +radius.apply(this, (argv[0] = t, argv)), + ta0 = startAngle.apply(this, argv) - halfPi$2, + ta1 = endAngle.apply(this, argv) - halfPi$2; + + if (!context) context = buffer = path(); + + context.moveTo(sx0, sy0); + context.arc(0, 0, sr, sa0, sa1); + if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? + context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); + context.arc(0, 0, tr, ta0, ta1); + } + context.quadraticCurveTo(0, 0, sx0, sy0); + context.closePath(); + + if (buffer) return context = null, buffer + "" || null; + } + + ribbon.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$12(+_), ribbon) : radius; + }; + + ribbon.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : startAngle; + }; + + ribbon.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : endAngle; + }; + + ribbon.source = function(_) { + return arguments.length ? (source = _, ribbon) : source; + }; + + ribbon.target = function(_) { + return arguments.length ? (target = _, ribbon) : target; + }; + + ribbon.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; + }; + + return ribbon; +}; + +// Adds floating point numbers with twice the normal precision. +// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and +// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) +// 305–363 (1997). +// Code adapted from GeographicLib by Charles F. F. Karney, +// http://geographiclib.sourceforge.net/ + +var adder = function() { + return new Adder; +}; + +function Adder() { + this.reset(); +} + +Adder.prototype = { + constructor: Adder, + reset: function() { + this.s = // rounded value + this.t = 0; // exact error + }, + add: function(y) { + add$1(temp, y, this.t); + add$1(this, temp.s, this.s); + if (this.s) this.t += temp.t; + else this.s = temp.t; + }, + valueOf: function() { + return this.s; + } +}; + +var temp = new Adder; + +function add$1(adder, a, b) { + var x = adder.s = a + b, + bv = x - a, + av = x - bv; + adder.t = (a - av) + (b - bv); +} + +var epsilon$4 = 1e-6; +var epsilon2$2 = 1e-12; +var pi$4 = Math.PI; +var halfPi$3 = pi$4 / 2; +var quarterPi = pi$4 / 4; +var tau$4 = pi$4 * 2; + +var degrees$1 = 180 / pi$4; +var radians = pi$4 / 180; + +var abs = Math.abs; +var atan = Math.atan; +var atan2 = Math.atan2; +var cos$1 = Math.cos; +var ceil = Math.ceil; +var exp = Math.exp; + +var log$1 = Math.log; +var pow$1 = Math.pow; +var sin$1 = Math.sin; +var sign$1 = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; +var sqrt$1 = Math.sqrt; +var tan = Math.tan; + +function acos(x) { + return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x); +} + +function asin$1(x) { + return x > 1 ? halfPi$3 : x < -1 ? -halfPi$3 : Math.asin(x); +} + +function haversin(x) { + return (x = sin$1(x / 2)) * x; +} + +function noop$2() {} + +function streamGeometry(geometry, stream) { + if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { + streamGeometryType[geometry.type](geometry, stream); + } +} + +var streamObjectType = { + Feature: function(feature, stream) { + streamGeometry(feature.geometry, stream); + }, + FeatureCollection: function(object, stream) { + var features = object.features, i = -1, n = features.length; + while (++i < n) streamGeometry(features[i].geometry, stream); + } +}; + +var streamGeometryType = { + Sphere: function(object, stream) { + stream.sphere(); + }, + Point: function(object, stream) { + object = object.coordinates; + stream.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); + }, + LineString: function(object, stream) { + streamLine(object.coordinates, stream, 0); + }, + MultiLineString: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamLine(coordinates[i], stream, 0); + }, + Polygon: function(object, stream) { + streamPolygon(object.coordinates, stream); + }, + MultiPolygon: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamPolygon(coordinates[i], stream); + }, + GeometryCollection: function(object, stream) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) streamGeometry(geometries[i], stream); + } +}; + +function streamLine(coordinates, stream, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + stream.lineStart(); + while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); + stream.lineEnd(); +} + +function streamPolygon(coordinates, stream) { + var i = -1, n = coordinates.length; + stream.polygonStart(); + while (++i < n) streamLine(coordinates[i], stream, 1); + stream.polygonEnd(); +} + +var geoStream = function(object, stream) { + if (object && streamObjectType.hasOwnProperty(object.type)) { + streamObjectType[object.type](object, stream); + } else { + streamGeometry(object, stream); + } +}; + +var areaRingSum = adder(); + +var areaSum = adder(); +var lambda00; +var phi00; +var lambda0; +var cosPhi0; +var sinPhi0; + +var areaStream = { + point: noop$2, + lineStart: noop$2, + lineEnd: noop$2, + polygonStart: function() { + areaRingSum.reset(); + areaStream.lineStart = areaRingStart; + areaStream.lineEnd = areaRingEnd; + }, + polygonEnd: function() { + var areaRing = +areaRingSum; + areaSum.add(areaRing < 0 ? tau$4 + areaRing : areaRing); + this.lineStart = this.lineEnd = this.point = noop$2; + }, + sphere: function() { + areaSum.add(tau$4); + } +}; + +function areaRingStart() { + areaStream.point = areaPointFirst; +} + +function areaRingEnd() { + areaPoint(lambda00, phi00); +} + +function areaPointFirst(lambda, phi) { + areaStream.point = areaPoint; + lambda00 = lambda, phi00 = phi; + lambda *= radians, phi *= radians; + lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi); +} + +function areaPoint(lambda, phi) { + lambda *= radians, phi *= radians; + phi = phi / 2 + quarterPi; // half the angular distance from south pole + + // Spherical excess E for a spherical triangle with vertices: south pole, + // previous point, current point. Uses a formula derived from Cagnoli’s + // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). + var dLambda = lambda - lambda0, + sdLambda = dLambda >= 0 ? 1 : -1, + adLambda = sdLambda * dLambda, + cosPhi = cos$1(phi), + sinPhi = sin$1(phi), + k = sinPhi0 * sinPhi, + u = cosPhi0 * cosPhi + k * cos$1(adLambda), + v = k * sdLambda * sin$1(adLambda); + areaRingSum.add(atan2(v, u)); + + // Advance the previous points. + lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; +} + +var area$2 = function(object) { + areaSum.reset(); + geoStream(object, areaStream); + return areaSum * 2; +}; + +function spherical(cartesian) { + return [atan2(cartesian[1], cartesian[0]), asin$1(cartesian[2])]; +} + +function cartesian(spherical) { + var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi); + return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)]; +} + +function cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +function 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]]; +} + +// TODO return a +function cartesianAddInPlace(a, b) { + a[0] += b[0], a[1] += b[1], a[2] += b[2]; +} + +function cartesianScale(vector, k) { + return [vector[0] * k, vector[1] * k, vector[2] * k]; +} + +// TODO return d +function cartesianNormalizeInPlace(d) { + var l = sqrt$1(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l, d[1] /= l, d[2] /= l; +} + +var lambda0$1; +var phi0; +var lambda1; +var phi1; +var lambda2; +var lambda00$1; +var phi00$1; +var p0; +var deltaSum = adder(); +var ranges; +var range$1; + +var boundsStream = { + point: boundsPoint, + lineStart: boundsLineStart, + lineEnd: boundsLineEnd, + polygonStart: function() { + boundsStream.point = boundsRingPoint; + boundsStream.lineStart = boundsRingStart; + boundsStream.lineEnd = boundsRingEnd; + deltaSum.reset(); + areaStream.polygonStart(); + }, + polygonEnd: function() { + areaStream.polygonEnd(); + boundsStream.point = boundsPoint; + boundsStream.lineStart = boundsLineStart; + boundsStream.lineEnd = boundsLineEnd; + if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); + else if (deltaSum > epsilon$4) phi1 = 90; + else if (deltaSum < -epsilon$4) phi0 = -90; + range$1[0] = lambda0$1, range$1[1] = lambda1; + } +}; + +function boundsPoint(lambda, phi) { + ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]); + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; +} + +function linePoint(lambda, phi) { + var p = cartesian([lambda * radians, phi * radians]); + if (p0) { + var normal = cartesianCross(p0, p), + equatorial = [normal[1], -normal[0], 0], + inflection = cartesianCross(equatorial, normal); + cartesianNormalizeInPlace(inflection); + inflection = spherical(inflection); + var delta = lambda - lambda2, + sign$$1 = delta > 0 ? 1 : -1, + lambdai = inflection[0] * degrees$1 * sign$$1, + phii, + antimeridian = abs(delta) > 180; + if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = inflection[1] * degrees$1; + if (phii > phi1) phi1 = phii; + } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = -inflection[1] * degrees$1; + if (phii < phi0) phi0 = phii; + } else { + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; + } + if (antimeridian) { + if (lambda < lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } else { + if (lambda1 >= lambda0$1) { + if (lambda < lambda0$1) lambda0$1 = lambda; + if (lambda > lambda1) lambda1 = lambda; + } else { + if (lambda > lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } + } + } else { + boundsPoint(lambda, phi); + } + p0 = p, lambda2 = lambda; +} + +function boundsLineStart() { + boundsStream.point = linePoint; +} + +function boundsLineEnd() { + range$1[0] = lambda0$1, range$1[1] = lambda1; + boundsStream.point = boundsPoint; + p0 = null; +} + +function boundsRingPoint(lambda, phi) { + if (p0) { + var delta = lambda - lambda2; + deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); + } else { + lambda00$1 = lambda, phi00$1 = phi; + } + areaStream.point(lambda, phi); + linePoint(lambda, phi); +} + +function boundsRingStart() { + areaStream.lineStart(); +} + +function boundsRingEnd() { + boundsRingPoint(lambda00$1, phi00$1); + areaStream.lineEnd(); + if (abs(deltaSum) > epsilon$4) lambda0$1 = -(lambda1 = 180); + range$1[0] = lambda0$1, range$1[1] = lambda1; + p0 = null; +} + +// Finds the left-right distance between two longitudes. +// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want +// the distance between ±180° to be 360°. +function angle(lambda0, lambda1) { + return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; +} + +function rangeCompare(a, b) { + return a[0] - b[0]; +} + +function rangeContains(range, x) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; +} + +var bounds = function(feature) { + var i, n, a, b, merged, deltaMax, delta; + + phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); + ranges = []; + geoStream(feature, boundsStream); + + // First, sort ranges by their minimum longitudes. + if (n = ranges.length) { + ranges.sort(rangeCompare); + + // Then, merge any ranges that overlap. + for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { + b = ranges[i]; + if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { + 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); + } + } + + // Finally, find the largest gap between the merged ranges. + // The final bounding box will be the inverse of this gap. + for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { + b = merged[i]; + if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; + } + } + + ranges = range$1 = null; + + return lambda0$1 === Infinity || phi0 === Infinity + ? [[NaN, NaN], [NaN, NaN]] + : [[lambda0$1, phi0], [lambda1, phi1]]; +}; + +var W0; +var W1; +var X0; +var Y0; +var Z0; +var X1; +var Y1; +var Z1; +var X2; +var Y2; +var Z2; +var lambda00$2; +var phi00$2; +var x0; +var y0; +var z0; // previous point + +var centroidStream = { + sphere: noop$2, + point: centroidPoint, + lineStart: centroidLineStart, + lineEnd: centroidLineEnd, + polygonStart: function() { + centroidStream.lineStart = centroidRingStart; + centroidStream.lineEnd = centroidRingEnd; + }, + polygonEnd: function() { + centroidStream.lineStart = centroidLineStart; + centroidStream.lineEnd = centroidLineEnd; + } +}; + +// Arithmetic mean of Cartesian vectors. +function centroidPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)); +} + +function centroidPointCartesian(x, y, z) { + ++W0; + X0 += (x - X0) / W0; + Y0 += (y - Y0) / W0; + Z0 += (z - Z0) / W0; +} + +function centroidLineStart() { + centroidStream.point = centroidLinePointFirst; +} + +function centroidLinePointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidStream.point = centroidLinePoint; + centroidPointCartesian(x0, y0, z0); +} + +function centroidLinePoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + w = atan2(sqrt$1((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); +} + +function centroidLineEnd() { + centroidStream.point = centroidPoint; +} + +// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, +// J. Applied Mechanics 42, 239 (1975). +function centroidRingStart() { + centroidStream.point = centroidRingPointFirst; +} + +function centroidRingEnd() { + centroidRingPoint(lambda00$2, phi00$2); + centroidStream.point = centroidPoint; +} + +function centroidRingPointFirst(lambda, phi) { + lambda00$2 = lambda, phi00$2 = phi; + lambda *= radians, phi *= radians; + centroidStream.point = centroidRingPoint; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidPointCartesian(x0, y0, z0); +} + +function centroidRingPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + cx = y0 * z - z0 * y, + cy = z0 * x - x0 * z, + cz = x0 * y - y0 * x, + m = sqrt$1(cx * cx + cy * cy + cz * cz), + u = x0 * x + y0 * y + z0 * z, + v = m && -acos(u) / m, // area weight + w = atan2(m, u); // line weight + X2 += v * cx; + Y2 += v * cy; + Z2 += v * cz; + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); +} + +var centroid$1 = function(object) { + W0 = W1 = + X0 = Y0 = Z0 = + X1 = Y1 = Z1 = + X2 = Y2 = Z2 = 0; + geoStream(object, centroidStream); + + var x = X2, + y = Y2, + z = Z2, + m = x * x + y * y + z * z; + + // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. + if (m < epsilon2$2) { + x = X1, y = Y1, z = Z1; + // If the feature has zero length, fall back to arithmetic mean of point vectors. + if (W1 < epsilon$4) x = X0, y = Y0, z = Z0; + m = x * x + y * y + z * z; + // If the feature still has an undefined ccentroid, then return. + if (m < epsilon2$2) return [NaN, NaN]; + } + + return [atan2(y, x) * degrees$1, asin$1(z / sqrt$1(m)) * degrees$1]; +}; + +var constant$13 = function(x) { + return function() { + return x; + }; +}; + +var compose = function(a, b) { + + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + + 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 rotationIdentity(lambda, phi) { + return [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi]; +} + +rotationIdentity.invert = rotationIdentity; + +function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { + return (deltaLambda %= tau$4) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) + : rotationLambda(deltaLambda)) + : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) + : rotationIdentity); +} + +function forwardRotationLambda(deltaLambda) { + return function(lambda, phi) { + return lambda += deltaLambda, [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi]; + }; +} + +function rotationLambda(deltaLambda) { + var rotation = forwardRotationLambda(deltaLambda); + rotation.invert = forwardRotationLambda(-deltaLambda); + return rotation; +} + +function rotationPhiGamma(deltaPhi, deltaGamma) { + var cosDeltaPhi = cos$1(deltaPhi), + sinDeltaPhi = sin$1(deltaPhi), + cosDeltaGamma = cos$1(deltaGamma), + sinDeltaGamma = sin$1(deltaGamma); + + function rotation(lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaPhi + x * sinDeltaPhi; + return [ + atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), + asin$1(k * cosDeltaGamma + y * sinDeltaGamma) + ]; + } + + rotation.invert = function(lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaGamma - y * sinDeltaGamma; + return [ + atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), + asin$1(k * cosDeltaPhi - x * sinDeltaPhi) + ]; + }; + + return rotation; +} + +var rotation = function(rotate) { + rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); + + function forward(coordinates) { + coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + } + + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + }; + + return forward; +}; + +// Generates a circle centered at [0°, 0°], with a given radius and precision. +function circleStream(stream, radius, delta, direction, t0, t1) { + if (!delta) return; + var cosRadius = cos$1(radius), + sinRadius = sin$1(radius), + step = direction * delta; + if (t0 == null) { + t0 = radius + direction * tau$4; + t1 = radius - step / 2; + } else { + t0 = circleRadius(cosRadius, t0); + t1 = circleRadius(cosRadius, t1); + if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$4; + } + for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { + point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]); + stream.point(point[0], point[1]); + } +} + +// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. +function circleRadius(cosRadius, point) { + point = cartesian(point), point[0] -= cosRadius; + cartesianNormalizeInPlace(point); + var radius = acos(-point[1]); + return ((-point[2] < 0 ? -radius : radius) + tau$4 - epsilon$4) % tau$4; +} + +var circle$1 = function() { + var center = constant$13([0, 0]), + radius = constant$13(90), + precision = constant$13(6), + ring, + rotate, + stream = {point: point}; + + function point(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= degrees$1, x[1] *= degrees$1; + } + + function circle() { + var c = center.apply(this, arguments), + r = radius.apply(this, arguments) * radians, + p = precision.apply(this, arguments) * radians; + ring = []; + rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; + circleStream(stream, r, p, 1); + c = {type: "Polygon", coordinates: [ring]}; + ring = rotate = null; + return c; + } + + circle.center = function(_) { + return arguments.length ? (center = typeof _ === "function" ? _ : constant$13([+_[0], +_[1]]), circle) : center; + }; + + circle.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$13(+_), circle) : radius; + }; + + circle.precision = function(_) { + return arguments.length ? (precision = typeof _ === "function" ? _ : constant$13(+_), circle) : precision; + }; + + return circle; +}; + +var clipBuffer = function() { + var lines = [], + line; + return { + point: function(x, y) { + line.push([x, y]); + }, + lineStart: function() { + lines.push(line = []); + }, + lineEnd: noop$2, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + }, + result: function() { + var result = lines; + lines = []; + line = null; + return result; + } + }; +}; + +var clipLine = function(a, b, x0, y0, x1, y1) { + var ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + 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) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; + if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; + return true; +}; + +var pointEqual = function(a, b) { + return abs(a[0] - b[0]) < epsilon$4 && abs(a[1] - b[1]) < epsilon$4; +}; + +function Intersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; // another intersection + this.e = entry; // is an entry? + this.v = false; // visited + this.n = this.p = null; // next & previous +} + +// A generalized polygon clipping algorithm: given a polygon that has been cut +// into its visible line segments, and rejoins the segments by interpolating +// along the clip edge. +var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) { + var subject = [], + clip = [], + i, + n; + + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n], x; + + // If the first and last points of a segment are coincident, then treat as a + // closed ring. TODO if all rings are closed, then the winding order of the + // exterior ring should be checked. + if (pointEqual(p0, p1)) { + stream.lineStart(); + for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); + stream.lineEnd(); + return; + } + + subject.push(x = new Intersection(p0, segment, null, true)); + clip.push(x.o = new Intersection(p0, null, x, false)); + subject.push(x = new Intersection(p1, segment, null, false)); + clip.push(x.o = new Intersection(p1, null, x, true)); + }); + + if (!subject.length) return; + + clip.sort(compareIntersection); + link$1(subject); + link$1(clip); + + for (i = 0, n = clip.length; i < n; ++i) { + clip[i].e = startInside = !startInside; + } + + var start = subject[0], + points, + point; + + while (1) { + // Find first unvisited intersection. + var current = start, + isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + stream.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, stream); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, stream); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + stream.lineEnd(); + } +}; + +function link$1(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; +} + +var clipMax = 1e9; +var clipMin = -clipMax; + +// TODO Use d3-polygon’s polygonContains here for the ring check? +// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? + +function clipExtent(x0, y0, x1, y1) { + + function visible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + + function interpolate(from, to, direction, stream) { + var a = 0, a1 = 0; + if (from == null + || (a = corner(from, direction)) !== (a1 = corner(to, direction)) + || comparePoint(from, to) < 0 ^ direction > 0) { + do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + while ((a = (a + direction + 4) % 4) !== a1); + } else { + stream.point(to[0], to[1]); + } + } + + function corner(p, direction) { + return abs(p[0] - x0) < epsilon$4 ? direction > 0 ? 0 : 3 + : abs(p[0] - x1) < epsilon$4 ? direction > 0 ? 2 : 1 + : abs(p[1] - y0) < epsilon$4 ? direction > 0 ? 1 : 0 + : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon + } + + function compareIntersection(a, b) { + return comparePoint(a.x, b.x); + } + + function comparePoint(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]; + } + + return function(stream) { + var activeStream = stream, + bufferStream = clipBuffer(), + segments, + polygon, + ring, + x__, y__, v__, // first point + x_, y_, v_, // previous point + first, + clean; + + var clipStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: polygonStart, + polygonEnd: polygonEnd + }; + + function point(x, y) { + if (visible(x, y)) activeStream.point(x, y); + } + + function polygonInside() { + var winding = 0; + + for (var i = 0, n = polygon.length; i < n; ++i) { + for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { + a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; + if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } + else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } + } + } + + return winding; + } + + // Buffer geometry within a polygon and then clip it en masse. + function polygonStart() { + activeStream = bufferStream, segments = [], polygon = [], clean = true; + } + + function polygonEnd() { + var startInside = polygonInside(), + cleanInside = clean && startInside, + visible = (segments = merge(segments)).length; + if (cleanInside || visible) { + stream.polygonStart(); + if (cleanInside) { + stream.lineStart(); + interpolate(null, null, 1, stream); + stream.lineEnd(); + } + if (visible) { + clipPolygon(segments, compareIntersection, startInside, interpolate, stream); + } + stream.polygonEnd(); + } + activeStream = stream, segments = polygon = ring = null; + } + + function lineStart() { + clipStream.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + + // TODO rather than special-case polygons, simply handle them separately. + // Ideally, coincident intersection points should be jittered to avoid + // clipping issues. + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferStream.rejoin(); + segments.push(bufferStream.result()); + } + clipStream.point = point; + if (v_) activeStream.lineEnd(); + } + + function linePoint(x, y) { + var v = visible(x, y); + if (polygon) ring.push([x, y]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + } + } else { + if (v && v_) activeStream.point(x, y); + else { + var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], + b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; + if (clipLine(a, b, x0, y0, x1, y1)) { + if (!v_) { + activeStream.lineStart(); + activeStream.point(a[0], a[1]); + } + activeStream.point(b[0], b[1]); + if (!v) activeStream.lineEnd(); + clean = false; + } else if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + + return clipStream; + }; +} + +var extent$1 = function() { + var x0 = 0, + y0 = 0, + x1 = 960, + y1 = 500, + cache, + cacheStream, + clip; + + return clip = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream); + }, + extent: function(_) { + return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; + } + }; +}; + +var lengthSum = adder(); +var lambda0$2; +var sinPhi0$1; +var cosPhi0$1; + +var lengthStream = { + sphere: noop$2, + point: noop$2, + lineStart: lengthLineStart, + lineEnd: noop$2, + polygonStart: noop$2, + polygonEnd: noop$2 +}; + +function lengthLineStart() { + lengthStream.point = lengthPointFirst; + lengthStream.lineEnd = lengthLineEnd; +} + +function lengthLineEnd() { + lengthStream.point = lengthStream.lineEnd = noop$2; +} + +function lengthPointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi); + lengthStream.point = lengthPoint; +} + +function lengthPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var sinPhi = sin$1(phi), + cosPhi = cos$1(phi), + delta = abs(lambda - lambda0$2), + cosDelta = cos$1(delta), + sinDelta = sin$1(delta), + x = cosPhi * sinDelta, + y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, + z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; + lengthSum.add(atan2(sqrt$1(x * x + y * y), z)); + lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; +} + +var length$2 = function(object) { + lengthSum.reset(); + geoStream(object, lengthStream); + return +lengthSum; +}; + +var coordinates = [null, null]; +var object$1 = {type: "LineString", coordinates: coordinates}; + +var distance = function(a, b) { + coordinates[0] = a; + coordinates[1] = b; + return length$2(object$1); +}; + +function graticuleX(y0, y1, dy) { + var y = range(y0, y1 - epsilon$4, dy).concat(y1); + return function(x) { return y.map(function(y) { return [x, y]; }); }; +} + +function graticuleY(x0, x1, dx) { + var x = range(x0, x1 - epsilon$4, dx).concat(x1); + return function(y) { return x.map(function(x) { return [x, y]; }); }; +} + +function graticule() { + 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 range(ceil(X0 / DX) * DX, X1, DX).map(X) + .concat(range(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) + .concat(range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$4; }).map(x)) + .concat(range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$4; }).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.extentMinor(); + return graticule.extentMajor(_).extentMinor(_); + }; + + graticule.extentMajor = 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.extentMinor = 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.stepMinor(); + return graticule.stepMajor(_).stepMinor(_); + }; + + graticule.stepMajor = function(_) { + if (!arguments.length) return [DX, DY]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + + graticule.stepMinor = function(_) { + if (!arguments.length) return [dx, dy]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = graticuleX(y0, y1, 90); + y = graticuleY(x0, x1, precision); + X = graticuleX(Y0, Y1, 90); + Y = graticuleY(X0, X1, precision); + return graticule; + }; + + return graticule + .extentMajor([[-180, -90 + epsilon$4], [180, 90 - epsilon$4]]) + .extentMinor([[-180, -80 - epsilon$4], [180, 80 + epsilon$4]]); +} + +function graticule10() { + return graticule()(); +} + +var interpolate$2 = function(a, b) { + var x0 = a[0] * radians, + y0 = a[1] * radians, + x1 = b[0] * radians, + y1 = b[1] * radians, + cy0 = cos$1(y0), + sy0 = sin$1(y0), + cy1 = cos$1(y1), + sy1 = sin$1(y1), + kx0 = cy0 * cos$1(x0), + ky0 = cy0 * sin$1(x0), + kx1 = cy1 * cos$1(x1), + ky1 = cy1 * sin$1(x1), + d = 2 * asin$1(sqrt$1(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), + k = sin$1(d); + + var interpolate = d ? function(t) { + var B = sin$1(t *= d) / k, + A = sin$1(d - t) / k, + x = A * kx0 + B * kx1, + y = A * ky0 + B * ky1, + z = A * sy0 + B * sy1; + return [ + atan2(y, x) * degrees$1, + atan2(z, sqrt$1(x * x + y * y)) * degrees$1 + ]; + } : function() { + return [x0 * degrees$1, y0 * degrees$1]; + }; + + interpolate.distance = d; + + return interpolate; +}; + +var identity$7 = function(x) { + return x; +}; + +var areaSum$1 = adder(); +var areaRingSum$1 = adder(); +var x00; +var y00; +var x0$1; +var y0$1; + +var areaStream$1 = { + point: noop$2, + lineStart: noop$2, + lineEnd: noop$2, + polygonStart: function() { + areaStream$1.lineStart = areaRingStart$1; + areaStream$1.lineEnd = areaRingEnd$1; + }, + polygonEnd: function() { + areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$2; + areaSum$1.add(abs(areaRingSum$1)); + areaRingSum$1.reset(); + }, + result: function() { + var area = areaSum$1 / 2; + areaSum$1.reset(); + return area; + } +}; + +function areaRingStart$1() { + areaStream$1.point = areaPointFirst$1; +} + +function areaPointFirst$1(x, y) { + areaStream$1.point = areaPoint$1; + x00 = x0$1 = x, y00 = y0$1 = y; +} + +function areaPoint$1(x, y) { + areaRingSum$1.add(y0$1 * x - x0$1 * y); + x0$1 = x, y0$1 = y; +} + +function areaRingEnd$1() { + areaPoint$1(x00, y00); +} + +var x0$2 = Infinity; +var y0$2 = x0$2; +var x1 = -x0$2; +var y1 = x1; + +var boundsStream$1 = { + point: boundsPoint$1, + lineStart: noop$2, + lineEnd: noop$2, + polygonStart: noop$2, + polygonEnd: noop$2, + result: function() { + var bounds = [[x0$2, y0$2], [x1, y1]]; + x1 = y1 = -(y0$2 = x0$2 = Infinity); + return bounds; + } +}; + +function boundsPoint$1(x, y) { + if (x < x0$2) x0$2 = x; + if (x > x1) x1 = x; + if (y < y0$2) y0$2 = y; + if (y > y1) y1 = y; +} + +// TODO Enforce positive area for exterior, negative area for interior? + +var X0$1 = 0; +var Y0$1 = 0; +var Z0$1 = 0; +var X1$1 = 0; +var Y1$1 = 0; +var Z1$1 = 0; +var X2$1 = 0; +var Y2$1 = 0; +var Z2$1 = 0; +var x00$1; +var y00$1; +var x0$3; +var y0$3; + +var centroidStream$1 = { + point: centroidPoint$1, + lineStart: centroidLineStart$1, + lineEnd: centroidLineEnd$1, + polygonStart: function() { + centroidStream$1.lineStart = centroidRingStart$1; + centroidStream$1.lineEnd = centroidRingEnd$1; + }, + polygonEnd: function() { + centroidStream$1.point = centroidPoint$1; + centroidStream$1.lineStart = centroidLineStart$1; + centroidStream$1.lineEnd = centroidLineEnd$1; + }, + result: function() { + var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] + : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] + : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] + : [NaN, NaN]; + X0$1 = Y0$1 = Z0$1 = + X1$1 = Y1$1 = Z1$1 = + X2$1 = Y2$1 = Z2$1 = 0; + return centroid; + } +}; + +function centroidPoint$1(x, y) { + X0$1 += x; + Y0$1 += y; + ++Z0$1; +} + +function centroidLineStart$1() { + centroidStream$1.point = centroidPointFirstLine; +} + +function centroidPointFirstLine(x, y) { + centroidStream$1.point = centroidPointLine; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function centroidPointLine(x, y) { + var dx = x - x0$3, dy = y - y0$3, z = sqrt$1(dx * dx + dy * dy); + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function centroidLineEnd$1() { + centroidStream$1.point = centroidPoint$1; +} + +function centroidRingStart$1() { + centroidStream$1.point = centroidPointFirstRing; +} + +function centroidRingEnd$1() { + centroidPointRing(x00$1, y00$1); +} + +function centroidPointFirstRing(x, y) { + centroidStream$1.point = centroidPointRing; + centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); +} + +function centroidPointRing(x, y) { + var dx = x - x0$3, + dy = y - y0$3, + z = sqrt$1(dx * dx + dy * dy); + + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + + z = y0$3 * x - x0$3 * y; + X2$1 += z * (x0$3 + x); + Y2$1 += z * (y0$3 + y); + Z2$1 += z * 3; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function PathContext(context) { + this._context = context; +} + +PathContext.prototype = { + _radius: 4.5, + pointRadius: function(_) { + return this._radius = _, this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._context.closePath(); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._context.moveTo(x, y); + this._point = 1; + break; + } + case 1: { + this._context.lineTo(x, y); + break; + } + default: { + this._context.moveTo(x + this._radius, y); + this._context.arc(x, y, this._radius, 0, tau$4); + break; + } + } + }, + result: noop$2 +}; + +function PathString() { + this._string = []; +} + +PathString.prototype = { + _circle: circle$2(4.5), + pointRadius: function(_) { + return this._circle = circle$2(_), this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._string.push("Z"); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._string.push("M", x, ",", y); + this._point = 1; + break; + } + case 1: { + this._string.push("L", x, ",", y); + break; + } + default: { + this._string.push("M", x, ",", y, this._circle); + break; + } + } + }, + result: function() { + if (this._string.length) { + var result = this._string.join(""); + this._string = []; + return result; + } + } +}; + +function circle$2(radius) { + return "m0," + radius + + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + + "z"; +} + +var index$3 = function(projection, context) { + var pointRadius = 4.5, + projectionStream, + contextStream; + + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + geoStream(object, projectionStream(contextStream)); + } + return contextStream.result(); + } + + path.area = function(object) { + geoStream(object, projectionStream(areaStream$1)); + return areaStream$1.result(); + }; + + path.bounds = function(object) { + geoStream(object, projectionStream(boundsStream$1)); + return boundsStream$1.result(); + }; + + path.centroid = function(object) { + geoStream(object, projectionStream(centroidStream$1)); + return centroidStream$1.result(); + }; + + path.projection = function(_) { + return arguments.length ? (projectionStream = (projection = _) == null ? identity$7 : _.stream, path) : projection; + }; + + path.context = function(_) { + if (!arguments.length) return context; + contextStream = (context = _) == null ? new PathString : new PathContext(_); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return path; + }; + + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + + return path.projection(projection).context(context); +}; + +var sum$2 = adder(); + +var polygonContains = function(polygon, point) { + var lambda = point[0], + phi = point[1], + normal = [sin$1(lambda), -cos$1(lambda), 0], + angle = 0, + winding = 0; + + sum$2.reset(); + + for (var i = 0, n = polygon.length; i < n; ++i) { + if (!(m = (ring = polygon[i]).length)) continue; + var ring, + m, + point0 = ring[m - 1], + lambda0 = point0[0], + phi0 = point0[1] / 2 + quarterPi, + sinPhi0 = sin$1(phi0), + cosPhi0 = cos$1(phi0); + + for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { + var point1 = ring[j], + lambda1 = point1[0], + phi1 = point1[1] / 2 + quarterPi, + sinPhi1 = sin$1(phi1), + cosPhi1 = cos$1(phi1), + delta = lambda1 - lambda0, + sign$$1 = delta >= 0 ? 1 : -1, + absDelta = sign$$1 * delta, + antimeridian = absDelta > pi$4, + k = sinPhi0 * sinPhi1; + + sum$2.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta))); + angle += antimeridian ? delta + sign$$1 * tau$4 : delta; + + // Are the longitudes either side of the point’s meridian (lambda), + // and are the latitudes smaller than the parallel (phi)? + if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { + var arc = cartesianCross(cartesian(point0), cartesian(point1)); + cartesianNormalizeInPlace(arc); + var intersection = cartesianCross(normal, arc); + cartesianNormalizeInPlace(intersection); + var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin$1(intersection[2]); + if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { + winding += antimeridian ^ delta >= 0 ? 1 : -1; + } + } + } + } + + // First, determine whether the South pole is inside or outside: + // + // It is inside if: + // * the polygon winds around it in a clockwise direction. + // * the polygon does not (cumulatively) wind around it, but has a negative + // (counter-clockwise) area. + // + // Second, count the (signed) number of times a segment crosses a lambda + // from the point to the South pole. If it is zero, then the point is the + // same side as the South pole. + + return (angle < -epsilon$4 || angle < epsilon$4 && sum$2 < -epsilon$4) ^ (winding & 1); +}; + +var clip = function(pointVisible, clipLine, interpolate, start) { + return function(rotate, sink) { + var line = clipLine(sink), + rotatedStart = rotate.invert(start[0], start[1]), + ringBuffer = clipBuffer(), + ringSink = clipLine(ringBuffer), + polygonStarted = false, + polygon, + segments, + ring; + + 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 = merge(segments); + var startInside = polygonContains(polygon, rotatedStart); + if (segments.length) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + clipPolygon(segments, compareIntersection, startInside, interpolate, sink); + } else if (startInside) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + } + if (polygonStarted) sink.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + sink.polygonStart(); + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + sink.polygonEnd(); + } + }; + + function point(lambda, phi) { + var point = rotate(lambda, phi); + if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi); + } + + function pointLine(lambda, phi) { + var point = rotate(lambda, phi); + line.point(point[0], point[1]); + } + + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + + function pointRing(lambda, phi) { + ring.push([lambda, phi]); + var point = rotate(lambda, phi); + ringSink.point(point[0], point[1]); + } + + function ringStart() { + ringSink.lineStart(); + ring = []; + } + + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringSink.lineEnd(); + + var clean = ringSink.clean(), + ringSegments = ringBuffer.result(), + i, n = ringSegments.length, m, + segment, + point; + + ring.pop(); + polygon.push(ring); + ring = null; + + if (!n) return; + + // No intersections. + if (clean & 1) { + segment = ringSegments[0]; + if ((m = segment.length - 1) > 0) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); + sink.lineEnd(); + } + return; + } + + // Rejoin connected segments. + // TODO reuse ringBuffer.rejoin()? + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + + segments.push(ringSegments.filter(validSegment)); + } + + return clip; + }; +}; + +function validSegment(segment) { + return segment.length > 1; +} + +// Intersections are sorted along the clip edge. For both antimeridian cutting +// and circle clipping, the same comparison is used. +function compareIntersection(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfPi$3 - epsilon$4 : halfPi$3 - a[1]) + - ((b = b.x)[0] < 0 ? b[1] - halfPi$3 - epsilon$4 : halfPi$3 - b[1]); +} + +var clipAntimeridian = clip( + function() { return true; }, + clipAntimeridianLine, + clipAntimeridianInterpolate, + [-pi$4, -halfPi$3] +); + +// Takes a line and cuts into visible segments. Return values: 0 - there were +// intersections or the line was empty; 1 - no intersections; 2 - there were +// intersections, and the first and last segments should be rejoined. +function clipAntimeridianLine(stream) { + var lambda0 = NaN, + phi0 = NaN, + sign0 = NaN, + clean; // no intersections + + return { + lineStart: function() { + stream.lineStart(); + clean = 1; + }, + point: function(lambda1, phi1) { + var sign1 = lambda1 > 0 ? pi$4 : -pi$4, + delta = abs(lambda1 - lambda0); + if (abs(delta - pi$4) < epsilon$4) { // line crosses a pole + stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$3 : -halfPi$3); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + stream.point(lambda1, phi0); + clean = 0; + } else if (sign0 !== sign1 && delta >= pi$4) { // line crosses antimeridian + if (abs(lambda0 - sign0) < epsilon$4) lambda0 -= sign0 * epsilon$4; // handle degeneracies + if (abs(lambda1 - sign1) < epsilon$4) lambda1 -= sign1 * epsilon$4; + phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + clean = 0; + } + stream.point(lambda0 = lambda1, phi0 = phi1); + sign0 = sign1; + }, + lineEnd: function() { + stream.lineEnd(); + lambda0 = phi0 = NaN; + }, + clean: function() { + return 2 - clean; // if intersections, rejoin first and last segments + } + }; +} + +function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { + var cosPhi0, + cosPhi1, + sinLambda0Lambda1 = sin$1(lambda0 - lambda1); + return abs(sinLambda0Lambda1) > epsilon$4 + ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1) + - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0)) + / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) + : (phi0 + phi1) / 2; +} + +function clipAntimeridianInterpolate(from, to, direction, stream) { + var phi; + if (from == null) { + phi = direction * halfPi$3; + stream.point(-pi$4, phi); + stream.point(0, phi); + stream.point(pi$4, phi); + stream.point(pi$4, 0); + stream.point(pi$4, -phi); + stream.point(0, -phi); + stream.point(-pi$4, -phi); + stream.point(-pi$4, 0); + stream.point(-pi$4, phi); + } else if (abs(from[0] - to[0]) > epsilon$4) { + var lambda = from[0] < to[0] ? pi$4 : -pi$4; + phi = direction * lambda / 2; + stream.point(-lambda, phi); + stream.point(0, phi); + stream.point(lambda, phi); + } else { + stream.point(to[0], to[1]); + } +} + +var clipCircle = function(radius, delta) { + var cr = cos$1(radius), + smallRadius = cr > 0, + notHemisphere = abs(cr) > epsilon$4; // TODO optimise for this common case + + function interpolate(from, to, direction, stream) { + circleStream(stream, radius, delta, direction, from, to); + } + + function visible(lambda, phi) { + return cos$1(lambda) * cos$1(phi) > cr; + } + + // Takes a line and cuts into visible segments. Return values used for polygon + // clipping: 0 - there were intersections or the line was empty; 1 - no + // intersections 2 - there were intersections, and the first and last segments + // should be rejoined. + function clipLine(stream) { + var point0, // previous point + c0, // code for previous point + v0, // visibility of previous point + v00, // visibility of first point + clean; // no intersections + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(lambda, phi) { + var point1 = [lambda, phi], + point2, + v = visible(lambda, phi), + c = smallRadius + ? v ? 0 : code(lambda, phi) + : v ? code(lambda + (lambda < 0 ? pi$4 : -pi$4), phi) : 0; + if (!point0 && (v00 = v0 = v)) stream.lineStart(); + // Handle degeneracies. + // TODO ignore if not clipping polygons. + if (v !== v0) { + point2 = intersect(point0, point1); + if (pointEqual(point0, point2) || pointEqual(point1, point2)) { + point1[0] += epsilon$4; + point1[1] += epsilon$4; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + // outside going in + stream.lineStart(); + point2 = intersect(point1, point0); + stream.point(point2[0], point2[1]); + } else { + // inside going out + point2 = intersect(point0, point1); + stream.point(point2[0], point2[1]); + stream.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + // If the codes for two points are different, or are both zero, + // and there this segment intersects with the small circle. + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + } else { + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !pointEqual(point0, point1))) { + stream.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) stream.lineEnd(); + point0 = null; + }, + // Rejoin first and last segments if there were intersections and the first + // and last points were visible. + clean: function() { + return clean | ((v00 && v0) << 1); + } + }; + } + + // Intersects the great circle between a and b with the clip circle. + function intersect(a, b, two) { + var pa = cartesian(a), + pb = cartesian(b); + + // We have two planes, n1.p = d1 and n2.p = d2. + // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). + var n1 = [1, 0, 0], // normal + n2 = cartesianCross(pa, pb), + n2n2 = cartesianDot(n2, n2), + n1n2 = n2[0], // cartesianDot(n1, n2), + determinant = n2n2 - n1n2 * n1n2; + + // Two polar points. + if (!determinant) return !two && a; + + var c1 = cr * n2n2 / determinant, + c2 = -cr * n1n2 / determinant, + n1xn2 = cartesianCross(n1, n2), + A = cartesianScale(n1, c1), + B = cartesianScale(n2, c2); + cartesianAddInPlace(A, B); + + // Solve |p(t)|^2 = 1. + var u = n1xn2, + w = cartesianDot(A, u), + uu = cartesianDot(u, u), + t2 = w * w - uu * (cartesianDot(A, A) - 1); + + if (t2 < 0) return; + + var t = sqrt$1(t2), + q = cartesianScale(u, (-w - t) / uu); + cartesianAddInPlace(q, A); + q = spherical(q); + + if (!two) return q; + + // Two intersection points. + var lambda0 = a[0], + lambda1 = b[0], + phi0 = a[1], + phi1 = b[1], + z; + + if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; + + var delta = lambda1 - lambda0, + polar = abs(delta - pi$4) < epsilon$4, + meridian = polar || delta < epsilon$4; + + if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; + + // Check that the first point is between a and b. + if (meridian + ? polar + ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$4 ? phi0 : phi1) + : phi0 <= q[1] && q[1] <= phi1 + : delta > pi$4 ^ (lambda0 <= q[0] && q[0] <= lambda1)) { + var q1 = cartesianScale(u, (-w + t) / uu); + cartesianAddInPlace(q1, A); + return [q, spherical(q1)]; + } + } + + // Generates a 4-bit vector representing the location of a point relative to + // the small circle's bounding box. + function code(lambda, phi) { + var r = smallRadius ? radius : pi$4 - radius, + code = 0; + if (lambda < -r) code |= 1; // left + else if (lambda > r) code |= 2; // right + if (phi < -r) code |= 4; // below + else if (phi > r) code |= 8; // above + return code; + } + + return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$4, radius - pi$4]); +}; + +var transform$1 = function(methods) { + return { + stream: transformer(methods) + }; +}; + +function transformer(methods) { + return function(stream) { + var s = new TransformStream; + for (var key in methods) s[key] = methods[key]; + s.stream = stream; + return s; + }; +} + +function TransformStream() {} + +TransformStream.prototype = { + constructor: TransformStream, + 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(); } +}; + +function fitExtent(projection, extent, object) { + var w = extent[1][0] - extent[0][0], + h = extent[1][1] - extent[0][1], + clip = projection.clipExtent && projection.clipExtent(); + + projection + .scale(150) + .translate([0, 0]); + + if (clip != null) projection.clipExtent(null); + + geoStream(object, projection.stream(boundsStream$1)); + + var b = boundsStream$1.result(), + k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), + x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, + y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; + + if (clip != null) projection.clipExtent(clip); + + return projection + .scale(k * 150) + .translate([x, y]); +} + +function fitSize(projection, size, object) { + return fitExtent(projection, [[0, 0], size], object); +} + +var maxDepth = 16; +var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance) + +var resample = function(project, delta2) { + return +delta2 ? resample$1(project, delta2) : resampleNone(project); +}; + +function resampleNone(project) { + return transformer({ + point: function(x, y) { + x = project(x, y); + this.stream.point(x[0], x[1]); + } + }); +} + +function resample$1(project, delta2) { + + function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, + dy = y1 - y0, + d2 = dx * dx + dy * dy; + if (d2 > 4 * delta2 && depth--) { + var a = a0 + a1, + b = b0 + b1, + c = c0 + c1, + m = sqrt$1(a * a + b * b + c * c), + phi2 = asin$1(c /= m), + lambda2 = abs(abs(c) - 1) < epsilon$4 || abs(lambda0 - lambda1) < epsilon$4 ? (lambda0 + lambda1) / 2 : atan2(b, a), + p = project(lambda2, phi2), + x2 = p[0], + y2 = p[1], + dx2 = x2 - x0, + dy2 = y2 - y0, + dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > delta2 // perpendicular projected distance + || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end + || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); + } + } + } + return function(stream) { + var lambda00, x00, y00, a00, b00, c00, // first point + lambda0, x0, y0, a0, b0, c0; // previous point + + var resampleStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; }, + polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; } + }; + + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + + function lineStart() { + x0 = NaN; + resampleStream.point = linePoint; + stream.lineStart(); + } + + function linePoint(lambda, phi) { + var c = cartesian([lambda, phi]), p = project(lambda, phi); + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + + function lineEnd() { + resampleStream.point = point; + stream.lineEnd(); + } + + function ringStart() { + lineStart(); + resampleStream.point = ringPoint; + resampleStream.lineEnd = ringEnd; + } + + function ringPoint(lambda, phi) { + linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resampleStream.point = linePoint; + } + + function ringEnd() { + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); + resampleStream.lineEnd = lineEnd; + lineEnd(); + } + + return resampleStream; + }; +} + +var transformRadians = transformer({ + point: function(x, y) { + this.stream.point(x * radians, y * radians); + } +}); + +function projection(project) { + return projectionMutator(function() { return project; })(); +} + +function projectionMutator(projectAt) { + var project, + k = 150, // scale + x = 480, y = 250, // translate + dx, dy, lambda = 0, phi = 0, // center + deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate + theta = null, preclip = clipAntimeridian, // clip angle + x0 = null, y0, x1, y1, postclip = identity$7, // clip extent + delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision + cache, + cacheStream; + + function projection(point) { + point = projectRotate(point[0] * radians, point[1] * radians); + return [point[0] * k + dx, dy - point[1] * k]; + } + + function invert(point) { + point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); + return point && [point[0] * degrees$1, point[1] * degrees$1]; + } + + function projectTransform(x, y) { + return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; + } + + projection.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream)))); + }; + + projection.clipAngle = function(_) { + return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1; + }; + + projection.clipExtent = function(_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$7) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + projection.scale = function(_) { + return arguments.length ? (k = +_, recenter()) : k; + }; + + projection.translate = function(_) { + return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; + }; + + projection.center = function(_) { + return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1]; + }; + + projection.rotate = function(_) { + return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1]; + }; + + projection.precision = function(_) { + return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt$1(delta2); + }; + + projection.fitExtent = function(extent, object) { + return fitExtent(projection, extent, object); + }; + + projection.fitSize = function(size, object) { + return fitSize(projection, size, object); + }; + + function recenter() { + projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project); + var center = project(lambda, phi); + dx = x - center[0] * k; + dy = y + center[1] * k; + return reset(); + } + + function reset() { + cache = cacheStream = null; + return projection; + } + + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return recenter(); + }; +} + +function conicProjection(projectAt) { + var phi0 = 0, + phi1 = pi$4 / 3, + m = projectionMutator(projectAt), + p = m(phi0, phi1); + + p.parallels = function(_) { + return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1]; + }; + + return p; +} + +function cylindricalEqualAreaRaw(phi0) { + var cosPhi0 = cos$1(phi0); + + function forward(lambda, phi) { + return [lambda * cosPhi0, sin$1(phi) / cosPhi0]; + } + + forward.invert = function(x, y) { + return [x / cosPhi0, asin$1(y * cosPhi0)]; + }; + + return forward; +} + +function conicEqualAreaRaw(y0, y1) { + var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2; + + // Are the parallels symmetrical around the Equator? + if (abs(n) < epsilon$4) return cylindricalEqualAreaRaw(y0); + + var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt$1(c) / n; + + function project(x, y) { + var r = sqrt$1(c - 2 * n * sin$1(y)) / n; + return [r * sin$1(x *= n), r0 - r * cos$1(x)]; + } + + project.invert = function(x, y) { + var r0y = r0 - y; + return [atan2(x, abs(r0y)) / n * sign$1(r0y), asin$1((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; + }; + + return project; +} + +var conicEqualArea = function() { + return conicProjection(conicEqualAreaRaw) + .scale(155.424) + .center([0, 33.6442]); +}; + +var albers = function() { + return conicEqualArea() + .parallels([29.5, 45.5]) + .scale(1070) + .translate([480, 250]) + .rotate([96, 0]) + .center([-0.6, 38.7]); +}; + +// The projections must have mutually exclusive clip regions on the sphere, +// as this will avoid emitting interleaving lines and polygons. +function multiplex(streams) { + var n = streams.length; + return { + point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); }, + sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); }, + lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); }, + lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); }, + polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); }, + polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); } + }; +} + +// A composite projection for the United States, configured by default for +// 960×500. The projection also works quite well at 960×600 if you change the +// scale to 1285 and adjust the translate accordingly. The set of standard +// parallels for each region comes from USGS, which is published here: +// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers +var albersUsa = function() { + var cache, + cacheStream, + lower48 = albers(), lower48Point, + alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 + hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 + point, pointStream = {point: function(x, y) { point = [x, y]; }}; + + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + return point = null, + (lower48Point.point(x, y), point) + || (alaskaPoint.point(x, y), point) + || (hawaiiPoint.point(x, y), 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 >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska + : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii + : lower48).invert(coordinates); + }; + + albersUsa.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); + }; + + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_), alaska.precision(_), hawaii.precision(_); + return reset(); + }; + + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_), alaska.scale(_ * 0.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 - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) + .stream(pointStream); + + alaskaPoint = alaska + .translate([x - 0.307 * k, y + 0.201 * k]) + .clipExtent([[x - 0.425 * k + epsilon$4, y + 0.120 * k + epsilon$4], [x - 0.214 * k - epsilon$4, y + 0.234 * k - epsilon$4]]) + .stream(pointStream); + + hawaiiPoint = hawaii + .translate([x - 0.205 * k, y + 0.212 * k]) + .clipExtent([[x - 0.214 * k + epsilon$4, y + 0.166 * k + epsilon$4], [x - 0.115 * k - epsilon$4, y + 0.234 * k - epsilon$4]]) + .stream(pointStream); + + return reset(); + }; + + albersUsa.fitExtent = function(extent, object) { + return fitExtent(albersUsa, extent, object); + }; + + albersUsa.fitSize = function(size, object) { + return fitSize(albersUsa, size, object); + }; + + function reset() { + cache = cacheStream = null; + return albersUsa; + } + + return albersUsa.scale(1070); +}; + +function azimuthalRaw(scale) { + return function(x, y) { + var cx = cos$1(x), + cy = cos$1(y), + k = scale(cx * cy); + return [ + k * cy * sin$1(x), + k * sin$1(y) + ]; + } +} + +function azimuthalInvert(angle) { + return function(x, y) { + var z = sqrt$1(x * x + y * y), + c = angle(z), + sc = sin$1(c), + cc = cos$1(c); + return [ + atan2(x * sc, z * cc), + asin$1(z && y * sc / z) + ]; + } +} + +var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { + return sqrt$1(2 / (1 + cxcy)); +}); + +azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { + return 2 * asin$1(z / 2); +}); + +var azimuthalEqualArea = function() { + return projection(azimuthalEqualAreaRaw) + .scale(124.75) + .clipAngle(180 - 1e-3); +}; + +var azimuthalEquidistantRaw = azimuthalRaw(function(c) { + return (c = acos(c)) && c / sin$1(c); +}); + +azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { + return z; +}); + +var azimuthalEquidistant = function() { + return projection(azimuthalEquidistantRaw) + .scale(79.4188) + .clipAngle(180 - 1e-3); +}; + +function mercatorRaw(lambda, phi) { + return [lambda, log$1(tan((halfPi$3 + phi) / 2))]; +} + +mercatorRaw.invert = function(x, y) { + return [x, 2 * atan(exp(y)) - halfPi$3]; +}; + +var mercator = function() { + return mercatorProjection(mercatorRaw) + .scale(961 / tau$4); +}; + +function mercatorProjection(project) { + var m = projection(project), + scale = m.scale, + translate = m.translate, + clipExtent = m.clipExtent, + clipAuto; + + m.scale = function(_) { + return arguments.length ? (scale(_), clipAuto && m.clipExtent(null), m) : scale(); + }; + + m.translate = function(_) { + return arguments.length ? (translate(_), clipAuto && m.clipExtent(null), m) : translate(); + }; + + m.clipExtent = function(_) { + if (!arguments.length) return clipAuto ? null : clipExtent(); + if (clipAuto = _ == null) { + var k = pi$4 * scale(), + t = translate(); + _ = [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]]; + } + clipExtent(_); + return m; + }; + + return m.clipExtent(null); +} + +function tany(y) { + return tan((halfPi$3 + y) / 2); +} + +function conicConformalRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : log$1(cy0 / cos$1(y1)) / log$1(tany(y1) / tany(y0)), + f = cy0 * pow$1(tany(y0), n) / n; + + if (!n) return mercatorRaw; + + function project(x, y) { + if (f > 0) { if (y < -halfPi$3 + epsilon$4) y = -halfPi$3 + epsilon$4; } + else { if (y > halfPi$3 - epsilon$4) y = halfPi$3 - epsilon$4; } + var r = f / pow$1(tany(y), n); + return [r * sin$1(n * x), f - r * cos$1(n * x)]; + } + + project.invert = function(x, y) { + var fy = f - y, r = sign$1(n) * sqrt$1(x * x + fy * fy); + return [atan2(x, abs(fy)) / n * sign$1(fy), 2 * atan(pow$1(f / r, 1 / n)) - halfPi$3]; + }; + + return project; +} + +var conicConformal = function() { + return conicProjection(conicConformalRaw) + .scale(109.5) + .parallels([30, 30]); +}; + +function equirectangularRaw(lambda, phi) { + return [lambda, phi]; +} + +equirectangularRaw.invert = equirectangularRaw; + +var equirectangular = function() { + return projection(equirectangularRaw) + .scale(152.63); +}; + +function conicEquidistantRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0), + g = cy0 / n + y0; + + if (abs(n) < epsilon$4) return equirectangularRaw; + + function project(x, y) { + var gy = g - y, nx = n * x; + return [gy * sin$1(nx), g - gy * cos$1(nx)]; + } + + project.invert = function(x, y) { + var gy = g - y; + return [atan2(x, abs(gy)) / n * sign$1(gy), g - sign$1(n) * sqrt$1(x * x + gy * gy)]; + }; + + return project; +} + +var conicEquidistant = function() { + return conicProjection(conicEquidistantRaw) + .scale(131.154) + .center([0, 13.9389]); +}; + +function gnomonicRaw(x, y) { + var cy = cos$1(y), k = cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; +} + +gnomonicRaw.invert = azimuthalInvert(atan); + +var gnomonic = function() { + return projection(gnomonicRaw) + .scale(144.049) + .clipAngle(60); +}; + +function scaleTranslate(k, tx, ty) { + return k === 1 && tx === 0 && ty === 0 ? identity$7 : transformer({ + point: function(x, y) { + this.stream.point(x * k + tx, y * k + ty); + } + }); +} + +var identity$8 = function() { + var k = 1, tx = 0, ty = 0, transform = identity$7, // scale and translate + x0 = null, y0, x1, y1, clip = identity$7, // clip extent + cache, + cacheStream, + projection; + + function reset() { + cache = cacheStream = null; + return projection; + } + + return projection = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream)); + }, + clipExtent: function(_) { + return arguments.length ? (clip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$7) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }, + scale: function(_) { + return arguments.length ? (transform = scaleTranslate(k = +_, tx, ty), reset()) : k; + }, + translate: function(_) { + return arguments.length ? (transform = scaleTranslate(k, tx = +_[0], ty = +_[1]), reset()) : [tx, ty]; + }, + fitExtent: function(extent, object) { + return fitExtent(projection, extent, object); + }, + fitSize: function(size, object) { + return fitSize(projection, size, object); + } + }; +}; + +function orthographicRaw(x, y) { + return [cos$1(y) * sin$1(x), sin$1(y)]; +} + +orthographicRaw.invert = azimuthalInvert(asin$1); + +var orthographic = function() { + return projection(orthographicRaw) + .scale(249.5) + .clipAngle(90 + epsilon$4); +}; + +function stereographicRaw(x, y) { + var cy = cos$1(y), k = 1 + cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; +} + +stereographicRaw.invert = azimuthalInvert(function(z) { + return 2 * atan(z); +}); + +var stereographic = function() { + return projection(stereographicRaw) + .scale(250) + .clipAngle(142); +}; + +function transverseMercatorRaw(lambda, phi) { + return [log$1(tan((halfPi$3 + phi) / 2)), -lambda]; +} + +transverseMercatorRaw.invert = function(x, y) { + return [-y, 2 * atan(exp(x)) - halfPi$3]; +}; + +var transverseMercator = function() { + var m = mercatorProjection(transverseMercatorRaw), + center = m.center, + rotate = m.rotate; + + m.center = function(_) { + return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); + }; + + m.rotate = function(_) { + return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); + }; + + return rotate([0, 0, 90]) + .scale(159.155); +}; + +exports.version = version; +exports.bisect = bisectRight; +exports.bisectRight = bisectRight; +exports.bisectLeft = bisectLeft; +exports.ascending = ascending; +exports.bisector = bisector; +exports.descending = descending; +exports.deviation = deviation; +exports.extent = extent; +exports.histogram = histogram; +exports.thresholdFreedmanDiaconis = freedmanDiaconis; +exports.thresholdScott = scott; +exports.thresholdSturges = sturges; +exports.max = max; +exports.mean = mean; +exports.median = median; +exports.merge = merge; +exports.min = min; +exports.pairs = pairs; +exports.permute = permute; +exports.quantile = threshold; +exports.range = range; +exports.scan = scan; +exports.shuffle = shuffle; +exports.sum = sum; +exports.ticks = ticks; +exports.tickStep = tickStep; +exports.transpose = transpose; +exports.variance = variance; +exports.zip = zip; +exports.entries = entries; +exports.keys = keys; +exports.values = values; +exports.map = map$1; +exports.set = set; +exports.nest = nest; +exports.randomUniform = uniform; +exports.randomNormal = normal; +exports.randomLogNormal = logNormal; +exports.randomBates = bates; +exports.randomIrwinHall = irwinHall; +exports.randomExponential = exponential; +exports.easeLinear = linear; +exports.easeQuad = quadInOut; +exports.easeQuadIn = quadIn; +exports.easeQuadOut = quadOut; +exports.easeQuadInOut = quadInOut; +exports.easeCubic = cubicInOut; +exports.easeCubicIn = cubicIn; +exports.easeCubicOut = cubicOut; +exports.easeCubicInOut = cubicInOut; +exports.easePoly = polyInOut; +exports.easePolyIn = polyIn; +exports.easePolyOut = polyOut; +exports.easePolyInOut = polyInOut; +exports.easeSin = sinInOut; +exports.easeSinIn = sinIn; +exports.easeSinOut = sinOut; +exports.easeSinInOut = sinInOut; +exports.easeExp = expInOut; +exports.easeExpIn = expIn; +exports.easeExpOut = expOut; +exports.easeExpInOut = expInOut; +exports.easeCircle = circleInOut; +exports.easeCircleIn = circleIn; +exports.easeCircleOut = circleOut; +exports.easeCircleInOut = circleInOut; +exports.easeBounce = bounceOut; +exports.easeBounceIn = bounceIn; +exports.easeBounceOut = bounceOut; +exports.easeBounceInOut = bounceInOut; +exports.easeBack = backInOut; +exports.easeBackIn = backIn; +exports.easeBackOut = backOut; +exports.easeBackInOut = backInOut; +exports.easeElastic = elasticOut; +exports.easeElasticIn = elasticIn; +exports.easeElasticOut = elasticOut; +exports.easeElasticInOut = elasticInOut; +exports.polygonArea = area; +exports.polygonCentroid = centroid; +exports.polygonHull = hull; +exports.polygonContains = contains; +exports.polygonLength = length$1; +exports.path = path; +exports.quadtree = quadtree; +exports.queue = queue; +exports.arc = arc; +exports.area = area$1; +exports.line = line; +exports.pie = pie; +exports.radialArea = radialArea; +exports.radialLine = radialLine$1; +exports.symbol = symbol; +exports.symbols = symbols; +exports.symbolCircle = circle; +exports.symbolCross = cross$1; +exports.symbolDiamond = diamond; +exports.symbolSquare = square; +exports.symbolStar = star; +exports.symbolTriangle = triangle; +exports.symbolWye = wye; +exports.curveBasisClosed = basisClosed; +exports.curveBasisOpen = basisOpen; +exports.curveBasis = basis; +exports.curveBundle = bundle; +exports.curveCardinalClosed = cardinalClosed; +exports.curveCardinalOpen = cardinalOpen; +exports.curveCardinal = cardinal; +exports.curveCatmullRomClosed = catmullRomClosed; +exports.curveCatmullRomOpen = catmullRomOpen; +exports.curveCatmullRom = catmullRom; +exports.curveLinearClosed = linearClosed; +exports.curveLinear = curveLinear; +exports.curveMonotoneX = monotoneX; +exports.curveMonotoneY = monotoneY; +exports.curveNatural = natural; +exports.curveStep = step; +exports.curveStepAfter = stepAfter; +exports.curveStepBefore = stepBefore; +exports.stack = stack; +exports.stackOffsetExpand = expand; +exports.stackOffsetNone = none; +exports.stackOffsetSilhouette = silhouette; +exports.stackOffsetWiggle = wiggle; +exports.stackOrderAscending = ascending$1; +exports.stackOrderDescending = descending$2; +exports.stackOrderInsideOut = insideOut; +exports.stackOrderNone = none$1; +exports.stackOrderReverse = reverse; +exports.color = color; +exports.rgb = rgb; +exports.hsl = hsl; +exports.lab = lab; +exports.hcl = hcl; +exports.cubehelix = cubehelix; +exports.interpolate = interpolate; +exports.interpolateArray = array$1; +exports.interpolateDate = date; +exports.interpolateNumber = interpolateNumber; +exports.interpolateObject = object; +exports.interpolateRound = interpolateRound; +exports.interpolateString = interpolateString; +exports.interpolateTransformCss = interpolateTransformCss; +exports.interpolateTransformSvg = interpolateTransformSvg; +exports.interpolateZoom = interpolateZoom; +exports.interpolateRgb = interpolateRgb; +exports.interpolateRgbBasis = rgbBasis; +exports.interpolateRgbBasisClosed = rgbBasisClosed; +exports.interpolateHsl = hsl$2; +exports.interpolateHslLong = hslLong; +exports.interpolateLab = lab$1; +exports.interpolateHcl = hcl$2; +exports.interpolateHclLong = hclLong; +exports.interpolateCubehelix = cubehelix$2; +exports.interpolateCubehelixLong = cubehelixLong; +exports.interpolateBasis = basis$2; +exports.interpolateBasisClosed = basisClosed$1; +exports.quantize = quantize; +exports.dispatch = dispatch; +exports.dsvFormat = dsv; +exports.csvParse = csvParse; +exports.csvParseRows = csvParseRows; +exports.csvFormat = csvFormat; +exports.csvFormatRows = csvFormatRows; +exports.tsvParse = tsvParse; +exports.tsvParseRows = tsvParseRows; +exports.tsvFormat = tsvFormat; +exports.tsvFormatRows = tsvFormatRows; +exports.request = request; +exports.html = html; +exports.json = json; +exports.text = text; +exports.xml = xml; +exports.csv = csv$1; +exports.tsv = tsv$1; +exports.now = now; +exports.timer = timer; +exports.timerFlush = timerFlush; +exports.timeout = timeout$1; +exports.interval = interval$1; +exports.timeInterval = newInterval; +exports.timeMillisecond = millisecond; +exports.timeMilliseconds = milliseconds; +exports.timeSecond = second; +exports.timeSeconds = seconds; +exports.timeMinute = minute; +exports.timeMinutes = minutes; +exports.timeHour = hour; +exports.timeHours = hours; +exports.timeDay = day; +exports.timeDays = days; +exports.timeWeek = sunday; +exports.timeWeeks = sundays; +exports.timeSunday = sunday; +exports.timeSundays = sundays; +exports.timeMonday = monday; +exports.timeMondays = mondays; +exports.timeTuesday = tuesday; +exports.timeTuesdays = tuesdays; +exports.timeWednesday = wednesday; +exports.timeWednesdays = wednesdays; +exports.timeThursday = thursday; +exports.timeThursdays = thursdays; +exports.timeFriday = friday; +exports.timeFridays = fridays; +exports.timeSaturday = saturday; +exports.timeSaturdays = saturdays; +exports.timeMonth = month; +exports.timeMonths = months; +exports.timeYear = year; +exports.timeYears = years; +exports.utcMillisecond = millisecond; +exports.utcMilliseconds = milliseconds; +exports.utcSecond = second; +exports.utcSeconds = seconds; +exports.utcMinute = utcMinute; +exports.utcMinutes = utcMinutes; +exports.utcHour = utcHour; +exports.utcHours = utcHours; +exports.utcDay = utcDay; +exports.utcDays = utcDays; +exports.utcWeek = utcSunday; +exports.utcWeeks = utcSundays; +exports.utcSunday = utcSunday; +exports.utcSundays = utcSundays; +exports.utcMonday = utcMonday; +exports.utcMondays = utcMondays; +exports.utcTuesday = utcTuesday; +exports.utcTuesdays = utcTuesdays; +exports.utcWednesday = utcWednesday; +exports.utcWednesdays = utcWednesdays; +exports.utcThursday = utcThursday; +exports.utcThursdays = utcThursdays; +exports.utcFriday = utcFriday; +exports.utcFridays = utcFridays; +exports.utcSaturday = utcSaturday; +exports.utcSaturdays = utcSaturdays; +exports.utcMonth = utcMonth; +exports.utcMonths = utcMonths; +exports.utcYear = utcYear; +exports.utcYears = utcYears; +exports.formatLocale = formatLocale; +exports.formatDefaultLocale = defaultLocale; +exports.formatSpecifier = formatSpecifier; +exports.precisionFixed = precisionFixed; +exports.precisionPrefix = precisionPrefix; +exports.precisionRound = precisionRound; +exports.isoFormat = formatIso; +exports.isoParse = parseIso; +exports.timeFormatLocale = formatLocale$1; +exports.timeFormatDefaultLocale = defaultLocale$1; +exports.scaleBand = band; +exports.scalePoint = point$4; +exports.scaleIdentity = identity$4; +exports.scaleLinear = linear$2; +exports.scaleLog = log; +exports.scaleOrdinal = ordinal; +exports.scaleImplicit = implicit; +exports.scalePow = pow; +exports.scaleSqrt = sqrt; +exports.scaleQuantile = quantile$$1; +exports.scaleQuantize = quantize$1; +exports.scaleThreshold = threshold$1; +exports.scaleTime = time; +exports.scaleUtc = utcTime; +exports.schemeCategory10 = category10; +exports.schemeCategory20b = category20b; +exports.schemeCategory20c = category20c; +exports.schemeCategory20 = category20; +exports.scaleSequential = sequential; +exports.interpolateCubehelixDefault = cubehelix$3; +exports.interpolateRainbow = rainbow$1; +exports.interpolateWarm = warm; +exports.interpolateCool = cool; +exports.interpolateViridis = viridis; +exports.interpolateMagma = magma; +exports.interpolateInferno = inferno; +exports.interpolatePlasma = plasma; +exports.creator = creator; +exports.customEvent = customEvent; +exports.local = local; +exports.matcher = matcher$1; +exports.mouse = mouse; +exports.namespace = namespace; +exports.namespaces = namespaces; +exports.select = select; +exports.selectAll = selectAll; +exports.selection = selection; +exports.selector = selector; +exports.selectorAll = selectorAll; +exports.touch = touch; +exports.touches = touches; +exports.window = window; +exports.active = active; +exports.interrupt = interrupt; +exports.transition = transition; +exports.axisTop = axisTop; +exports.axisRight = axisRight; +exports.axisBottom = axisBottom; +exports.axisLeft = axisLeft; +exports.cluster = cluster; +exports.hierarchy = hierarchy; +exports.pack = index; +exports.packSiblings = siblings; +exports.packEnclose = enclose; +exports.partition = partition; +exports.stratify = stratify; +exports.tree = tree; +exports.treemap = index$1; +exports.treemapBinary = binary; +exports.treemapDice = treemapDice; +exports.treemapSlice = treemapSlice; +exports.treemapSliceDice = sliceDice; +exports.treemapSquarify = squarify; +exports.treemapResquarify = resquarify; +exports.forceCenter = center$1; +exports.forceCollide = collide; +exports.forceLink = link; +exports.forceManyBody = manyBody; +exports.forceSimulation = simulation; +exports.forceX = x$3; +exports.forceY = y$3; +exports.drag = drag; +exports.dragDisable = dragDisable; +exports.dragEnable = yesdrag; +exports.voronoi = voronoi; +exports.zoom = zoom; +exports.zoomIdentity = identity$6; +exports.zoomTransform = transform; +exports.brush = brush; +exports.brushX = brushX; +exports.brushY = brushY; +exports.brushSelection = brushSelection; +exports.chord = chord; +exports.ribbon = ribbon; +exports.geoAlbers = albers; +exports.geoAlbersUsa = albersUsa; +exports.geoArea = area$2; +exports.geoAzimuthalEqualArea = azimuthalEqualArea; +exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; +exports.geoAzimuthalEquidistant = azimuthalEquidistant; +exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; +exports.geoBounds = bounds; +exports.geoCentroid = centroid$1; +exports.geoCircle = circle$1; +exports.geoClipExtent = extent$1; +exports.geoConicConformal = conicConformal; +exports.geoConicConformalRaw = conicConformalRaw; +exports.geoConicEqualArea = conicEqualArea; +exports.geoConicEqualAreaRaw = conicEqualAreaRaw; +exports.geoConicEquidistant = conicEquidistant; +exports.geoConicEquidistantRaw = conicEquidistantRaw; +exports.geoDistance = distance; +exports.geoEquirectangular = equirectangular; +exports.geoEquirectangularRaw = equirectangularRaw; +exports.geoGnomonic = gnomonic; +exports.geoGnomonicRaw = gnomonicRaw; +exports.geoGraticule = graticule; +exports.geoGraticule10 = graticule10; +exports.geoIdentity = identity$8; +exports.geoInterpolate = interpolate$2; +exports.geoLength = length$2; +exports.geoMercator = mercator; +exports.geoMercatorRaw = mercatorRaw; +exports.geoOrthographic = orthographic; +exports.geoOrthographicRaw = orthographicRaw; +exports.geoPath = index$3; +exports.geoProjection = projection; +exports.geoProjectionMutator = projectionMutator; +exports.geoRotation = rotation; +exports.geoStereographic = stereographic; +exports.geoStereographicRaw = stereographicRaw; +exports.geoStream = geoStream; +exports.geoTransform = transform$1; +exports.geoTransverseMercator = transverseMercator; +exports.geoTransverseMercatorRaw = transverseMercatorRaw; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); From e16ba28cdfb29cb4a848badcb1b24f19919a0081 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 21 Nov 2016 13:28:31 -0800 Subject: [PATCH 10/85] Updated D3 to v4.3.0 --- chapter_04/01_empty_page_template.html | 2 +- chapter_05/01_empty_page_template.html | 2 +- chapter_05/02_new_element.html | 2 +- chapter_05/03_csv_loading_example.html | 2 +- chapter_05/04_creating_paragraphs.html | 2 +- chapter_05/05_creating_paragraphs_text.html | 2 +- chapter_05/06_creating_paragraphs_counting.html | 2 +- chapter_05/07_creating_paragraphs_with_style.html | 2 +- chapter_05/08_creating_paragraphs_with_style_functions.html | 2 +- chapter_06/01_drawing_divs.html | 2 +- chapter_06/02_drawing_divs_height.html | 2 +- chapter_06/03_drawing_divs_spaced.html | 2 +- chapter_06/04_power_of_data.html | 2 +- chapter_06/05_power_of_data_more_points.html | 2 +- chapter_06/06_power_of_data_random.html | 2 +- chapter_06/07_power_of_data_rounded.html | 2 +- chapter_06/08_drawing_svgs.html | 2 +- chapter_06/09_drawing_svgs_size.html | 2 +- chapter_06/10_drawing_svgs_circles.html | 2 +- chapter_06/11_drawing_svgs_color.html | 2 +- chapter_06/12_making_a_bar_chart_divs.html | 2 +- chapter_06/13_making_a_bar_chart_rects.html | 2 +- chapter_06/14_making_a_bar_chart_offset.html | 2 +- chapter_06/15_making_a_bar_chart_even.html | 2 +- chapter_06/16_making_a_bar_chart_widths.html | 2 +- chapter_06/17_making_a_bar_chart_heights.html | 2 +- chapter_06/18_making_a_bar_chart_teal.html | 2 +- chapter_06/19_making_a_bar_chart_blues.html | 2 +- chapter_06/20_making_a_bar_chart_labels.html | 2 +- chapter_06/21_making_a_bar_chart_aligned.html | 2 +- chapter_06/22_scatterplot.html | 2 +- chapter_06/23_scatterplot_sqrt.html | 2 +- chapter_06/24_scatterplot_labels.html | 2 +- chapter_07/01_scale_test.html | 2 +- chapter_07/02_scaled_plot.html | 2 +- chapter_07/03_scaled_plot_inverted.html | 2 +- chapter_07/04_scaled_plot_padding.html | 2 +- chapter_07/05_scaled_plot_radii.html | 2 +- chapter_07/06_scaled_plot_big.html | 2 +- chapter_07/07_scaled_plot_large.html | 2 +- chapter_08/01_axes.html | 2 +- chapter_08/02_axes_bottom.html | 2 +- chapter_08/03_axes_clean.html | 2 +- chapter_08/04_axes_y.html | 2 +- chapter_08/05_axes_random.html | 2 +- chapter_08/06_axes_no_labels.html | 2 +- chapter_08/07_axes_format.html | 2 +- chapter_09/01_bar_chart.html | 2 +- chapter_09/02_bar_chart_with_scales.html | 2 +- chapter_09/03_updates_all_data.html | 2 +- chapter_09/04_updates_all_data_fixed.html | 2 +- chapter_09/05_transition.html | 2 +- chapter_09/06_duration.html | 2 +- chapter_09/07_duration_slow.html | 2 +- chapter_09/08_duration_slow_labels_fixed.html | 2 +- chapter_09/09_ease_linear.html | 2 +- chapter_09/10_ease_circle.html | 2 +- chapter_09/11_ease_elastic.html | 2 +- chapter_09/12_ease_bounce.html | 2 +- chapter_09/13_delay_static.html | 2 +- chapter_09/14_delay_dynamic.html | 2 +- chapter_09/15_delay_dynamic_scaled.html | 2 +- chapter_09/16_delay_dynamic_scaled_fewer.html | 2 +- chapter_09/17_randomized_data.html | 2 +- chapter_09/18_dynamic_scale.html | 2 +- chapter_09/19_axes_static.html | 2 +- chapter_09/20_axes_dynamic.html | 2 +- chapter_09/21_each.html | 2 +- chapter_09/22_each_combo_transition.html | 2 +- chapter_09/23_each_combo_transition_chained.html | 2 +- chapter_09/24_clip-path.html | 2 +- chapter_09/25_adding_values.html | 2 +- chapter_09/26_removing_values.html | 2 +- chapter_09/27_data_join_with_key.html | 2 +- chapter_09/28_adding_and_removing.html | 2 +- chapter_09/29_dynamic_labels.html | 2 +- chapter_10/01_start.html | 2 +- chapter_10/02_click.html | 2 +- chapter_10/03_hover.html | 2 +- chapter_10/04_mouseover.html | 2 +- chapter_10/05_mouseout.html | 2 +- chapter_10/06_smoother.html | 2 +- chapter_10/07_sort.html | 2 +- chapter_10/08_sort_hover.html | 2 +- chapter_10/09_resort.html | 2 +- chapter_10/10_delay.html | 2 +- chapter_10/11_browser_tooltip.html | 2 +- chapter_10/12_browser_tooltip_text.html | 2 +- chapter_10/13_svg_tooltip.html | 2 +- chapter_10/14_div_tooltip.html | 2 +- chapter_11/01_pie.html | 2 +- chapter_11/02_ring.html | 2 +- chapter_11/03_stacked_bar.html | 2 +- chapter_11/04_force.html | 2 +- chapter_12/01_paths.html | 2 +- chapter_12/02_projection.html | 2 +- chapter_12/03_scaled.html | 2 +- chapter_12/04_fill.html | 2 +- chapter_12/05_choropleth.html | 2 +- chapter_12/06_points.html | 2 +- chapter_12/07_points_sized.html | 2 +- chapter_12/08_oceans.html | 2 +- chapter_12/09_mercator.html | 2 +- 103 files changed, 103 insertions(+), 103 deletions(-) diff --git a/chapter_04/01_empty_page_template.html b/chapter_04/01_empty_page_template.html index 35bb55f..078bb51 100644 --- a/chapter_04/01_empty_page_template.html +++ b/chapter_04/01_empty_page_template.html @@ -3,7 +3,7 @@ D3 Page Template - + + + + + + + + + + diff --git a/chapter_06/09_drawing_svgs_size.html b/chapter_06/09_drawing_svgs_size.html index 3ea96eb..6edacf9 100644 --- a/chapter_06/09_drawing_svgs_size.html +++ b/chapter_06/09_drawing_svgs_size.html @@ -3,7 +3,7 @@ D3: Putting the SVG's width and height into variables - + diff --git a/chapter_06/10_drawing_svgs_circles.html b/chapter_06/10_drawing_svgs_circles.html index ee4cea3..2fb46d1 100644 --- a/chapter_06/10_drawing_svgs_circles.html +++ b/chapter_06/10_drawing_svgs_circles.html @@ -3,7 +3,7 @@ D3: Drawing SVG circles with data - + diff --git a/chapter_06/11_drawing_svgs_color.html b/chapter_06/11_drawing_svgs_color.html index 5432cce..e3713b0 100644 --- a/chapter_06/11_drawing_svgs_color.html +++ b/chapter_06/11_drawing_svgs_color.html @@ -3,7 +3,7 @@ D3: Using color in SVG - + diff --git a/chapter_06/12_making_a_bar_chart_divs.html b/chapter_06/12_making_a_bar_chart_divs.html index 051fd03..2051ee2 100644 --- a/chapter_06/12_making_a_bar_chart_divs.html +++ b/chapter_06/12_making_a_bar_chart_divs.html @@ -3,7 +3,7 @@ D3: A bar chart with divs - + diff --git a/chapter_06/14_making_a_bar_chart_offset.html b/chapter_06/14_making_a_bar_chart_offset.html index 33fe509..9c1d55a 100644 --- a/chapter_06/14_making_a_bar_chart_offset.html +++ b/chapter_06/14_making_a_bar_chart_offset.html @@ -3,7 +3,7 @@ D3: Making a bar chart with SVG rects, spacing - + diff --git a/chapter_06/15_making_a_bar_chart_even.html b/chapter_06/15_making_a_bar_chart_even.html index cb1179b..57acbbf 100644 --- a/chapter_06/15_making_a_bar_chart_even.html +++ b/chapter_06/15_making_a_bar_chart_even.html @@ -3,7 +3,7 @@ D3: Making a bar chart with SVG rects, evenly spaced - + diff --git a/chapter_06/16_making_a_bar_chart_widths.html b/chapter_06/16_making_a_bar_chart_widths.html index 5fc984b..c1ce632 100644 --- a/chapter_06/16_making_a_bar_chart_widths.html +++ b/chapter_06/16_making_a_bar_chart_widths.html @@ -3,7 +3,7 @@ D3: Making a bar chart with SVG rects, dynamic widths and spacing - + diff --git a/chapter_06/17_making_a_bar_chart_heights.html b/chapter_06/17_making_a_bar_chart_heights.html index 7b3c67b..faf636a 100644 --- a/chapter_06/17_making_a_bar_chart_heights.html +++ b/chapter_06/17_making_a_bar_chart_heights.html @@ -3,7 +3,7 @@ D3: A true bar chart with SVG rects - + diff --git a/chapter_06/18_making_a_bar_chart_teal.html b/chapter_06/18_making_a_bar_chart_teal.html index 9d93fb1..afeac96 100644 --- a/chapter_06/18_making_a_bar_chart_teal.html +++ b/chapter_06/18_making_a_bar_chart_teal.html @@ -3,7 +3,7 @@ D3: Adding color to an SVG bar chart - + diff --git a/chapter_06/19_making_a_bar_chart_blues.html b/chapter_06/19_making_a_bar_chart_blues.html index 861cfdc..53d887f 100644 --- a/chapter_06/19_making_a_bar_chart_blues.html +++ b/chapter_06/19_making_a_bar_chart_blues.html @@ -3,7 +3,7 @@ D3: Adding dynamic color, based on data - + diff --git a/chapter_06/20_making_a_bar_chart_labels.html b/chapter_06/20_making_a_bar_chart_labels.html index a0560c4..58d35ea 100644 --- a/chapter_06/20_making_a_bar_chart_labels.html +++ b/chapter_06/20_making_a_bar_chart_labels.html @@ -3,7 +3,7 @@ D3: SVG bar chart with value labels - + diff --git a/chapter_06/21_making_a_bar_chart_aligned.html b/chapter_06/21_making_a_bar_chart_aligned.html index 82c5ec7..e8e0188 100644 --- a/chapter_06/21_making_a_bar_chart_aligned.html +++ b/chapter_06/21_making_a_bar_chart_aligned.html @@ -3,7 +3,7 @@ D3: SVG bar chart with value labels (centered) - + diff --git a/chapter_06/22_scatterplot.html b/chapter_06/22_scatterplot.html index 0d0b403..490dc10 100644 --- a/chapter_06/22_scatterplot.html +++ b/chapter_06/22_scatterplot.html @@ -3,7 +3,7 @@ D3: A simple scatterplot with SVG - + diff --git a/chapter_06/23_scatterplot_sqrt.html b/chapter_06/23_scatterplot_sqrt.html index 695e817..5873669 100644 --- a/chapter_06/23_scatterplot_sqrt.html +++ b/chapter_06/23_scatterplot_sqrt.html @@ -3,7 +3,7 @@ D3: A simple scatterplot, setting radii from data - + diff --git a/chapter_06/24_scatterplot_labels.html b/chapter_06/24_scatterplot_labels.html index 88a7749..bac10f6 100644 --- a/chapter_06/24_scatterplot_labels.html +++ b/chapter_06/24_scatterplot_labels.html @@ -3,7 +3,7 @@ D3: A simple scatterplot with value labels - + diff --git a/chapter_07/01_scale_test.html b/chapter_07/01_scale_test.html index 6717917..28f44c0 100644 --- a/chapter_07/01_scale_test.html +++ b/chapter_07/01_scale_test.html @@ -3,7 +3,7 @@ D3: Empty page for testing scale functions - + diff --git a/chapter_07/02_scaled_plot.html b/chapter_07/02_scaled_plot.html index e63b57e..76a27b4 100644 --- a/chapter_07/02_scaled_plot.html +++ b/chapter_07/02_scaled_plot.html @@ -3,7 +3,7 @@ D3: Linear scales with a scatterplot - + diff --git a/chapter_07/03_scaled_plot_inverted.html b/chapter_07/03_scaled_plot_inverted.html index 5c3bc19..adc414e 100644 --- a/chapter_07/03_scaled_plot_inverted.html +++ b/chapter_07/03_scaled_plot_inverted.html @@ -3,7 +3,7 @@ D3: An inverted linear scale - + diff --git a/chapter_07/04_scaled_plot_padding.html b/chapter_07/04_scaled_plot_padding.html index 4a4c4c5..51b2f2a 100644 --- a/chapter_07/04_scaled_plot_padding.html +++ b/chapter_07/04_scaled_plot_padding.html @@ -3,7 +3,7 @@ D3: Adding padding to the scatterplot - + diff --git a/chapter_07/05_scaled_plot_radii.html b/chapter_07/05_scaled_plot_radii.html index 2e5ed84..5524b2e 100644 --- a/chapter_07/05_scaled_plot_radii.html +++ b/chapter_07/05_scaled_plot_radii.html @@ -3,7 +3,7 @@ D3: Adjusted radii - + diff --git a/chapter_07/06_scaled_plot_big.html b/chapter_07/06_scaled_plot_big.html index d847f0f..e98095a 100644 --- a/chapter_07/06_scaled_plot_big.html +++ b/chapter_07/06_scaled_plot_big.html @@ -3,7 +3,7 @@ D3: Scaled scatterplot, with new (large) data value added - + diff --git a/chapter_07/07_scaled_plot_large.html b/chapter_07/07_scaled_plot_large.html index e847fc2..05ef3bc 100644 --- a/chapter_07/07_scaled_plot_large.html +++ b/chapter_07/07_scaled_plot_large.html @@ -3,7 +3,7 @@ D3: Scaled scatterplot, resized to be bigger! - + diff --git a/chapter_08/01_axes.html b/chapter_08/01_axes.html index fb26ae3..371b62d 100644 --- a/chapter_08/01_axes.html +++ b/chapter_08/01_axes.html @@ -3,7 +3,7 @@ D3: A simple, unstyled axis - + diff --git a/chapter_08/02_axes_bottom.html b/chapter_08/02_axes_bottom.html index ed81a44..d5212e7 100644 --- a/chapter_08/02_axes_bottom.html +++ b/chapter_08/02_axes_bottom.html @@ -3,7 +3,7 @@ D3: Axis moved to the bottom - + diff --git a/chapter_09/02_bar_chart_with_scales.html b/chapter_09/02_bar_chart_with_scales.html index 7321aa1..c433707 100644 --- a/chapter_09/02_bar_chart_with_scales.html +++ b/chapter_09/02_bar_chart_with_scales.html @@ -3,7 +3,7 @@ D3: A flexible, scalable bar chart - + diff --git a/chapter_09/03_updates_all_data.html b/chapter_09/03_updates_all_data.html index 39cdcd7..0ea9d91 100644 --- a/chapter_09/03_updates_all_data.html +++ b/chapter_09/03_updates_all_data.html @@ -3,7 +3,7 @@ D3: A bar chart whose data updates with new data - + diff --git a/chapter_09/04_updates_all_data_fixed.html b/chapter_09/04_updates_all_data_fixed.html index 94cdcba..ed2ed19 100644 --- a/chapter_09/04_updates_all_data_fixed.html +++ b/chapter_09/04_updates_all_data_fixed.html @@ -3,7 +3,7 @@ D3: A bar chart whose data updates with new data (labels, too) - + diff --git a/chapter_09/05_transition.html b/chapter_09/05_transition.html index 9e2aa94..e7edd2b 100644 --- a/chapter_09/05_transition.html +++ b/chapter_09/05_transition.html @@ -3,7 +3,7 @@ D3: A bar chart that transitions to new data! - + diff --git a/chapter_09/06_duration.html b/chapter_09/06_duration.html index 4d40143..b24fb50 100644 --- a/chapter_09/06_duration.html +++ b/chapter_09/06_duration.html @@ -3,7 +3,7 @@ D3: A chart transition with controlled duration - + diff --git a/chapter_09/07_duration_slow.html b/chapter_09/07_duration_slow.html index 14610a7..49e65a7 100644 --- a/chapter_09/07_duration_slow.html +++ b/chapter_09/07_duration_slow.html @@ -3,7 +3,7 @@ D3: A chart transition with controlled duration (slower) - + diff --git a/chapter_09/08_duration_slow_labels_fixed.html b/chapter_09/08_duration_slow_labels_fixed.html index 43b2192..4d18ab6 100644 --- a/chapter_09/08_duration_slow_labels_fixed.html +++ b/chapter_09/08_duration_slow_labels_fixed.html @@ -3,7 +3,7 @@ D3: A chart transition with controlled duration (labels, too!) - + diff --git a/chapter_09/09_ease_linear.html b/chapter_09/09_ease_linear.html index 3355805..1b14ba1 100644 --- a/chapter_09/09_ease_linear.html +++ b/chapter_09/09_ease_linear.html @@ -3,7 +3,7 @@ D3: Demo of linear easing - + diff --git a/chapter_09/10_ease_circle.html b/chapter_09/10_ease_circle.html index c1aa384..b3a60e5 100644 --- a/chapter_09/10_ease_circle.html +++ b/chapter_09/10_ease_circle.html @@ -3,7 +3,7 @@ D3: Demo of circle easing - + diff --git a/chapter_09/11_ease_elastic.html b/chapter_09/11_ease_elastic.html index 2990a3d..1759234 100644 --- a/chapter_09/11_ease_elastic.html +++ b/chapter_09/11_ease_elastic.html @@ -3,7 +3,7 @@ D3: Demo of elastic easing - + diff --git a/chapter_09/12_ease_bounce.html b/chapter_09/12_ease_bounce.html index 29ad777..a744355 100644 --- a/chapter_09/12_ease_bounce.html +++ b/chapter_09/12_ease_bounce.html @@ -3,7 +3,7 @@ D3: Demo of bounce easing - + diff --git a/chapter_09/13_delay_static.html b/chapter_09/13_delay_static.html index 6ba5110..9115512 100644 --- a/chapter_09/13_delay_static.html +++ b/chapter_09/13_delay_static.html @@ -3,7 +3,7 @@ D3: A static delay before transition - + diff --git a/chapter_09/14_delay_dynamic.html b/chapter_09/14_delay_dynamic.html index bba054e..5091926 100644 --- a/chapter_09/14_delay_dynamic.html +++ b/chapter_09/14_delay_dynamic.html @@ -3,7 +3,7 @@ D3: A dynamic, per-element delay before transition - + diff --git a/chapter_09/15_delay_dynamic_scaled.html b/chapter_09/15_delay_dynamic_scaled.html index 2dce0ec..95810c1 100644 --- a/chapter_09/15_delay_dynamic_scaled.html +++ b/chapter_09/15_delay_dynamic_scaled.html @@ -3,7 +3,7 @@ D3: A dynamic delay, with more elements - + diff --git a/chapter_09/16_delay_dynamic_scaled_fewer.html b/chapter_09/16_delay_dynamic_scaled_fewer.html index 5b49d5f..663e1b8 100644 --- a/chapter_09/16_delay_dynamic_scaled_fewer.html +++ b/chapter_09/16_delay_dynamic_scaled_fewer.html @@ -3,7 +3,7 @@ D3: A dynamic delay, with fewer elements - + diff --git a/chapter_09/17_randomized_data.html b/chapter_09/17_randomized_data.html index f48e4cd..9ec8c7e 100644 --- a/chapter_09/17_randomized_data.html +++ b/chapter_09/17_randomized_data.html @@ -3,7 +3,7 @@ D3: Transitioning to randomized data values - + diff --git a/chapter_09/18_dynamic_scale.html b/chapter_09/18_dynamic_scale.html index e9f374f..b7a9890 100644 --- a/chapter_09/18_dynamic_scale.html +++ b/chapter_09/18_dynamic_scale.html @@ -3,7 +3,7 @@ D3: Dynamically adjusting the vertical scale - + diff --git a/chapter_09/19_axes_static.html b/chapter_09/19_axes_static.html index e1d9a81..d34377a 100644 --- a/chapter_09/19_axes_static.html +++ b/chapter_09/19_axes_static.html @@ -3,7 +3,7 @@ D3: Transitioning points to randomized values - + diff --git a/chapter_09/26_removing_values.html b/chapter_09/26_removing_values.html index 4636cf6..3e6e539 100644 --- a/chapter_09/26_removing_values.html +++ b/chapter_09/26_removing_values.html @@ -3,7 +3,7 @@ D3: Removing values from a chart - + diff --git a/chapter_09/27_data_join_with_key.html b/chapter_09/27_data_join_with_key.html index 6552b23..cb3a424 100644 --- a/chapter_09/27_data_join_with_key.html +++ b/chapter_09/27_data_join_with_key.html @@ -3,7 +3,7 @@ D3: Removing values from a chart - + diff --git a/chapter_09/28_adding_and_removing.html b/chapter_09/28_adding_and_removing.html index 262eb99..df65749 100644 --- a/chapter_09/28_adding_and_removing.html +++ b/chapter_09/28_adding_and_removing.html @@ -3,7 +3,7 @@ D3: Adding and removing values from a chart - + diff --git a/chapter_09/29_dynamic_labels.html b/chapter_09/29_dynamic_labels.html index 330de9e..c1b15ef 100644 --- a/chapter_09/29_dynamic_labels.html +++ b/chapter_09/29_dynamic_labels.html @@ -3,7 +3,7 @@ D3: Adding and removing values from a chart (dynamic labels included) - + diff --git a/chapter_10/01_start.html b/chapter_10/01_start.html index bc7a214..f255e63 100644 --- a/chapter_10/01_start.html +++ b/chapter_10/01_start.html @@ -3,7 +3,7 @@ D3: A starting point for interactivity - + diff --git a/chapter_10/02_click.html b/chapter_10/02_click.html index 99ebb82..1d01ad4 100644 --- a/chapter_10/02_click.html +++ b/chapter_10/02_click.html @@ -3,7 +3,7 @@ D3: Click to log the data values to the console - + diff --git a/chapter_10/03_hover.html b/chapter_10/03_hover.html index ff47005..60d298e 100644 --- a/chapter_10/03_hover.html +++ b/chapter_10/03_hover.html @@ -3,7 +3,7 @@ D3: A simple CSS-only hover effect - + diff --git a/chapter_10/05_mouseout.html b/chapter_10/05_mouseout.html index 7b53de4..cb6448a 100644 --- a/chapter_10/05_mouseout.html +++ b/chapter_10/05_mouseout.html @@ -3,7 +3,7 @@ D3: Using D3 to change fill color on mouseover AND mouseout - + diff --git a/chapter_10/06_smoother.html b/chapter_10/06_smoother.html index 0a9e5af..ba90057 100644 --- a/chapter_10/06_smoother.html +++ b/chapter_10/06_smoother.html @@ -3,7 +3,7 @@ D3: Smoother highlight transitions - + diff --git a/chapter_10/07_sort.html b/chapter_10/07_sort.html index 2adb65d..1403e30 100644 --- a/chapter_10/07_sort.html +++ b/chapter_10/07_sort.html @@ -3,7 +3,7 @@ D3: Sorting visual elements - + diff --git a/chapter_10/08_sort_hover.html b/chapter_10/08_sort_hover.html index bde0898..c8bf393 100644 --- a/chapter_10/08_sort_hover.html +++ b/chapter_10/08_sort_hover.html @@ -3,7 +3,7 @@ D3: Sorting visual elements, with CSS-only hover highlight - + diff --git a/chapter_11/04_force.html b/chapter_11/04_force.html index cde8dad..6c3c918 100644 --- a/chapter_11/04_force.html +++ b/chapter_11/04_force.html @@ -3,7 +3,7 @@ D3: Force layout - + diff --git a/chapter_12/01_paths.html b/chapter_12/01_paths.html index 6265306..b2fc6a1 100644 --- a/chapter_12/01_paths.html +++ b/chapter_12/01_paths.html @@ -3,7 +3,7 @@ D3: Loading GeoJSON data and generating SVG paths - + diff --git a/chapter_12/02_projection.html b/chapter_12/02_projection.html index d550ad5..06e7593 100644 --- a/chapter_12/02_projection.html +++ b/chapter_12/02_projection.html @@ -3,7 +3,7 @@ D3: Applying a projection to SVG paths - + diff --git a/chapter_12/03_scaled.html b/chapter_12/03_scaled.html index 5b56d68..24595e8 100644 --- a/chapter_12/03_scaled.html +++ b/chapter_12/03_scaled.html @@ -3,7 +3,7 @@ D3: Scaling the AlbersUSA projection - + diff --git a/chapter_12/04_fill.html b/chapter_12/04_fill.html index 9495f14..c058d51 100644 --- a/chapter_12/04_fill.html +++ b/chapter_12/04_fill.html @@ -3,7 +3,7 @@ D3: Setting path fills - + diff --git a/chapter_12/05_choropleth.html b/chapter_12/05_choropleth.html index 2164395..c232581 100644 --- a/chapter_12/05_choropleth.html +++ b/chapter_12/05_choropleth.html @@ -3,7 +3,7 @@ D3: Setting path fills dynamically to generate a choropleth - + diff --git a/chapter_12/06_points.html b/chapter_12/06_points.html index 9ffe082..079633c 100644 --- a/chapter_12/06_points.html +++ b/chapter_12/06_points.html @@ -3,7 +3,7 @@ D3: Adding data points (circles) to the map - + diff --git a/chapter_12/07_points_sized.html b/chapter_12/07_points_sized.html index cc78944..c137bce 100644 --- a/chapter_12/07_points_sized.html +++ b/chapter_12/07_points_sized.html @@ -3,7 +3,7 @@ D3: Scaling the circles by data value - + diff --git a/chapter_12/08_oceans.html b/chapter_12/08_oceans.html index b3b87bb..3ad93bb 100644 --- a/chapter_12/08_oceans.html +++ b/chapter_12/08_oceans.html @@ -3,7 +3,7 @@ D3: Loading oceans GeoJSON data - + diff --git a/chapter_12/09_mercator.html b/chapter_12/09_mercator.html index 3ac5e53..509cf93 100644 --- a/chapter_12/09_mercator.html +++ b/chapter_12/09_mercator.html @@ -3,7 +3,7 @@ D3: Mercator projection applied to oceans - + From cdb0b8c7a6a6d1a61ad478863c1e12c45c4f8638 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 21 Nov 2016 16:03:37 -0800 Subject: [PATCH 11/85] Removed .gitignore --- .gitignore | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 9bea433..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ - -.DS_Store From 6800512bfacc534440ac621feeb83b9ca2c484e4 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 2 Dec 2016 14:39:35 -0800 Subject: [PATCH 12/85] Bye bye vegemite, hopefully liver won't offend anyone --- chapter_05/food.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapter_05/food.csv b/chapter_05/food.csv index 2ac578c..84c8a87 100644 --- a/chapter_05/food.csv +++ b/chapter_05/food.csv @@ -3,5 +3,5 @@ Apples,9 Green Beans,5 Egg Salad Sandwich,4 Cookies,10 -Vegemite,0.2 +Liver,0.2 Burrito,7 \ No newline at end of file From 463272a9e02e2632c8f70d07c94b1258bb2f7a74 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 2 Dec 2016 14:49:43 -0800 Subject: [PATCH 13/85] Updated all references from d3.scale.linear() to d3.scaleLinear() --- chapter_07/02_scaled_plot.html | 4 ++-- chapter_07/03_scaled_plot_inverted.html | 4 ++-- chapter_07/04_scaled_plot_padding.html | 4 ++-- chapter_07/05_scaled_plot_radii.html | 6 +++--- chapter_07/06_scaled_plot_big.html | 6 +++--- chapter_07/07_scaled_plot_large.html | 6 +++--- chapter_08/01_axes.html | 6 +++--- chapter_08/02_axes_bottom.html | 6 +++--- chapter_08/03_axes_clean.html | 6 +++--- chapter_08/04_axes_y.html | 6 +++--- chapter_08/05_axes_random.html | 6 +++--- chapter_08/06_axes_no_labels.html | 6 +++--- chapter_08/07_axes_format.html | 6 +++--- chapter_09/02_bar_chart_with_scales.html | 2 +- chapter_09/03_updates_all_data.html | 2 +- chapter_09/04_updates_all_data_fixed.html | 2 +- chapter_09/05_transition.html | 2 +- chapter_09/06_duration.html | 2 +- chapter_09/07_duration_slow.html | 2 +- chapter_09/08_duration_slow_labels_fixed.html | 2 +- chapter_09/09_ease_linear.html | 2 +- chapter_09/10_ease_circle.html | 2 +- chapter_09/11_ease_elastic.html | 2 +- chapter_09/12_ease_bounce.html | 2 +- chapter_09/13_delay_static.html | 2 +- chapter_09/14_delay_dynamic.html | 2 +- chapter_09/15_delay_dynamic_scaled.html | 2 +- chapter_09/16_delay_dynamic_scaled_fewer.html | 2 +- chapter_09/17_randomized_data.html | 2 +- chapter_09/18_dynamic_scale.html | 2 +- chapter_09/19_axes_static.html | 4 ++-- chapter_09/20_axes_dynamic.html | 4 ++-- chapter_09/21_each.html | 4 ++-- chapter_09/22_each_combo_transition.html | 4 ++-- chapter_09/23_each_combo_transition_chained.html | 4 ++-- chapter_09/24_clip-path.html | 4 ++-- chapter_09/25_adding_values.html | 2 +- chapter_09/26_removing_values.html | 2 +- chapter_09/27_data_join_with_key.html | 2 +- chapter_09/28_adding_and_removing.html | 2 +- chapter_09/29_dynamic_labels.html | 2 +- chapter_10/01_start.html | 2 +- chapter_10/02_click.html | 2 +- chapter_10/03_hover.html | 2 +- chapter_10/04_mouseover.html | 2 +- chapter_10/05_mouseout.html | 2 +- chapter_10/06_smoother.html | 2 +- chapter_10/07_sort.html | 2 +- chapter_10/08_sort_hover.html | 2 +- chapter_10/09_resort.html | 2 +- chapter_10/10_delay.html | 2 +- chapter_10/11_browser_tooltip.html | 2 +- chapter_10/12_browser_tooltip_text.html | 2 +- chapter_10/13_svg_tooltip.html | 2 +- chapter_10/14_div_tooltip.html | 2 +- chapter_11/03_stacked_bar.html | 2 +- 56 files changed, 85 insertions(+), 85 deletions(-) diff --git a/chapter_07/02_scaled_plot.html b/chapter_07/02_scaled_plot.html index 76a27b4..0c8b8f0 100644 --- a/chapter_07/02_scaled_plot.html +++ b/chapter_07/02_scaled_plot.html @@ -21,11 +21,11 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([0, w]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, h]); diff --git a/chapter_07/03_scaled_plot_inverted.html b/chapter_07/03_scaled_plot_inverted.html index adc414e..e6ca0c4 100644 --- a/chapter_07/03_scaled_plot_inverted.html +++ b/chapter_07/03_scaled_plot_inverted.html @@ -21,11 +21,11 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([0, w]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h, 0]); diff --git a/chapter_07/04_scaled_plot_padding.html b/chapter_07/04_scaled_plot_padding.html index 51b2f2a..fc3a9b7 100644 --- a/chapter_07/04_scaled_plot_padding.html +++ b/chapter_07/04_scaled_plot_padding.html @@ -22,11 +22,11 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); diff --git a/chapter_07/05_scaled_plot_radii.html b/chapter_07/05_scaled_plot_radii.html index 5524b2e..d3971d7 100644 --- a/chapter_07/05_scaled_plot_radii.html +++ b/chapter_07/05_scaled_plot_radii.html @@ -22,15 +22,15 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_07/06_scaled_plot_big.html b/chapter_07/06_scaled_plot_big.html index e98095a..3d770ae 100644 --- a/chapter_07/06_scaled_plot_big.html +++ b/chapter_07/06_scaled_plot_big.html @@ -23,15 +23,15 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_07/07_scaled_plot_large.html b/chapter_07/07_scaled_plot_large.html index 05ef3bc..f62972f 100644 --- a/chapter_07/07_scaled_plot_large.html +++ b/chapter_07/07_scaled_plot_large.html @@ -23,15 +23,15 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_08/01_axes.html b/chapter_08/01_axes.html index 371b62d..d01a0bb 100644 --- a/chapter_08/01_axes.html +++ b/chapter_08/01_axes.html @@ -23,15 +23,15 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_08/02_axes_bottom.html b/chapter_08/02_axes_bottom.html index d5212e7..6376795 100644 --- a/chapter_08/02_axes_bottom.html +++ b/chapter_08/02_axes_bottom.html @@ -35,15 +35,15 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_08/03_axes_clean.html b/chapter_08/03_axes_clean.html index 7cbd7e5..d783818 100644 --- a/chapter_08/03_axes_clean.html +++ b/chapter_08/03_axes_clean.html @@ -35,15 +35,15 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_08/04_axes_y.html b/chapter_08/04_axes_y.html index 0d17b7f..aed21d2 100644 --- a/chapter_08/04_axes_y.html +++ b/chapter_08/04_axes_y.html @@ -35,15 +35,15 @@ ]; //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_08/05_axes_random.html b/chapter_08/05_axes_random.html index fd426c3..275fa37 100644 --- a/chapter_08/05_axes_random.html +++ b/chapter_08/05_axes_random.html @@ -49,15 +49,15 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_08/06_axes_no_labels.html b/chapter_08/06_axes_no_labels.html index ae4dc38..7fd7e28 100644 --- a/chapter_08/06_axes_no_labels.html +++ b/chapter_08/06_axes_no_labels.html @@ -49,15 +49,15 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_08/07_axes_format.html b/chapter_08/07_axes_format.html index 4444802..a52b56a 100644 --- a/chapter_08/07_axes_format.html +++ b/chapter_08/07_axes_format.html @@ -49,15 +49,15 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scale.linear() + var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([2, 5]); diff --git a/chapter_09/02_bar_chart_with_scales.html b/chapter_09/02_bar_chart_with_scales.html index c433707..645e40e 100644 --- a/chapter_09/02_bar_chart_with_scales.html +++ b/chapter_09/02_bar_chart_with_scales.html @@ -22,7 +22,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/03_updates_all_data.html b/chapter_09/03_updates_all_data.html index 0ea9d91..de81d6a 100644 --- a/chapter_09/03_updates_all_data.html +++ b/chapter_09/03_updates_all_data.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/04_updates_all_data_fixed.html b/chapter_09/04_updates_all_data_fixed.html index ed2ed19..d6d18b9 100644 --- a/chapter_09/04_updates_all_data_fixed.html +++ b/chapter_09/04_updates_all_data_fixed.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/05_transition.html b/chapter_09/05_transition.html index e7edd2b..ba12265 100644 --- a/chapter_09/05_transition.html +++ b/chapter_09/05_transition.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/06_duration.html b/chapter_09/06_duration.html index b24fb50..c1402f9 100644 --- a/chapter_09/06_duration.html +++ b/chapter_09/06_duration.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/07_duration_slow.html b/chapter_09/07_duration_slow.html index 49e65a7..85f15a3 100644 --- a/chapter_09/07_duration_slow.html +++ b/chapter_09/07_duration_slow.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/08_duration_slow_labels_fixed.html b/chapter_09/08_duration_slow_labels_fixed.html index 4d18ab6..4911c71 100644 --- a/chapter_09/08_duration_slow_labels_fixed.html +++ b/chapter_09/08_duration_slow_labels_fixed.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/09_ease_linear.html b/chapter_09/09_ease_linear.html index 1b14ba1..1df8f4d 100644 --- a/chapter_09/09_ease_linear.html +++ b/chapter_09/09_ease_linear.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/10_ease_circle.html b/chapter_09/10_ease_circle.html index b3a60e5..fd6bf78 100644 --- a/chapter_09/10_ease_circle.html +++ b/chapter_09/10_ease_circle.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/11_ease_elastic.html b/chapter_09/11_ease_elastic.html index 1759234..2b02150 100644 --- a/chapter_09/11_ease_elastic.html +++ b/chapter_09/11_ease_elastic.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/12_ease_bounce.html b/chapter_09/12_ease_bounce.html index a744355..c32b292 100644 --- a/chapter_09/12_ease_bounce.html +++ b/chapter_09/12_ease_bounce.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/13_delay_static.html b/chapter_09/13_delay_static.html index 9115512..747290d 100644 --- a/chapter_09/13_delay_static.html +++ b/chapter_09/13_delay_static.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/14_delay_dynamic.html b/chapter_09/14_delay_dynamic.html index 5091926..a29f5ed 100644 --- a/chapter_09/14_delay_dynamic.html +++ b/chapter_09/14_delay_dynamic.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/15_delay_dynamic_scaled.html b/chapter_09/15_delay_dynamic_scaled.html index 95810c1..70121b1 100644 --- a/chapter_09/15_delay_dynamic_scaled.html +++ b/chapter_09/15_delay_dynamic_scaled.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/16_delay_dynamic_scaled_fewer.html b/chapter_09/16_delay_dynamic_scaled_fewer.html index 663e1b8..6d45adb 100644 --- a/chapter_09/16_delay_dynamic_scaled_fewer.html +++ b/chapter_09/16_delay_dynamic_scaled_fewer.html @@ -24,7 +24,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/17_randomized_data.html b/chapter_09/17_randomized_data.html index 9ec8c7e..41560ff 100644 --- a/chapter_09/17_randomized_data.html +++ b/chapter_09/17_randomized_data.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/18_dynamic_scale.html b/chapter_09/18_dynamic_scale.html index b7a9890..bf8dbca 100644 --- a/chapter_09/18_dynamic_scale.html +++ b/chapter_09/18_dynamic_scale.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/19_axes_static.html b/chapter_09/19_axes_static.html index d34377a..c5a95ac 100644 --- a/chapter_09/19_axes_static.html +++ b/chapter_09/19_axes_static.html @@ -42,11 +42,11 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); diff --git a/chapter_09/20_axes_dynamic.html b/chapter_09/20_axes_dynamic.html index e50b9f4..5789aee 100644 --- a/chapter_09/20_axes_dynamic.html +++ b/chapter_09/20_axes_dynamic.html @@ -42,11 +42,11 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); diff --git a/chapter_09/21_each.html b/chapter_09/21_each.html index 838c223..e73552b 100644 --- a/chapter_09/21_each.html +++ b/chapter_09/21_each.html @@ -42,11 +42,11 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); diff --git a/chapter_09/22_each_combo_transition.html b/chapter_09/22_each_combo_transition.html index 78b80f3..fb030fc 100644 --- a/chapter_09/22_each_combo_transition.html +++ b/chapter_09/22_each_combo_transition.html @@ -42,11 +42,11 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); diff --git a/chapter_09/23_each_combo_transition_chained.html b/chapter_09/23_each_combo_transition_chained.html index 9d3112b..bafd9e2 100644 --- a/chapter_09/23_each_combo_transition_chained.html +++ b/chapter_09/23_each_combo_transition_chained.html @@ -42,11 +42,11 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); diff --git a/chapter_09/24_clip-path.html b/chapter_09/24_clip-path.html index 6c4397e..6ad6d40 100644 --- a/chapter_09/24_clip-path.html +++ b/chapter_09/24_clip-path.html @@ -42,11 +42,11 @@ } //Create scale functions - var xScale = d3.scale.linear() + var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([padding, w - padding * 2]); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); diff --git a/chapter_09/25_adding_values.html b/chapter_09/25_adding_values.html index 9021b34..d703fda 100644 --- a/chapter_09/25_adding_values.html +++ b/chapter_09/25_adding_values.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/26_removing_values.html b/chapter_09/26_removing_values.html index 3e6e539..d9a5d8b 100644 --- a/chapter_09/26_removing_values.html +++ b/chapter_09/26_removing_values.html @@ -25,7 +25,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_09/27_data_join_with_key.html b/chapter_09/27_data_join_with_key.html index cb3a424..9b3872e 100644 --- a/chapter_09/27_data_join_with_key.html +++ b/chapter_09/27_data_join_with_key.html @@ -43,7 +43,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d.value; })]) .range([0, h]); diff --git a/chapter_09/28_adding_and_removing.html b/chapter_09/28_adding_and_removing.html index df65749..4761dec 100644 --- a/chapter_09/28_adding_and_removing.html +++ b/chapter_09/28_adding_and_removing.html @@ -44,7 +44,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d.value; })]) .range([0, h]); diff --git a/chapter_09/29_dynamic_labels.html b/chapter_09/29_dynamic_labels.html index c1b15ef..9cf7c8d 100644 --- a/chapter_09/29_dynamic_labels.html +++ b/chapter_09/29_dynamic_labels.html @@ -44,7 +44,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d.value; })]) .range([0, h]); diff --git a/chapter_10/01_start.html b/chapter_10/01_start.html index f255e63..147e573 100644 --- a/chapter_10/01_start.html +++ b/chapter_10/01_start.html @@ -22,7 +22,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/02_click.html b/chapter_10/02_click.html index 1d01ad4..043f95f 100644 --- a/chapter_10/02_click.html +++ b/chapter_10/02_click.html @@ -22,7 +22,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/03_hover.html b/chapter_10/03_hover.html index 60d298e..8366387 100644 --- a/chapter_10/03_hover.html +++ b/chapter_10/03_hover.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/04_mouseover.html b/chapter_10/04_mouseover.html index 3840dc0..3f7759e 100644 --- a/chapter_10/04_mouseover.html +++ b/chapter_10/04_mouseover.html @@ -22,7 +22,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/05_mouseout.html b/chapter_10/05_mouseout.html index cb6448a..86162f8 100644 --- a/chapter_10/05_mouseout.html +++ b/chapter_10/05_mouseout.html @@ -22,7 +22,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/06_smoother.html b/chapter_10/06_smoother.html index ba90057..b124d77 100644 --- a/chapter_10/06_smoother.html +++ b/chapter_10/06_smoother.html @@ -22,7 +22,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/07_sort.html b/chapter_10/07_sort.html index 1403e30..05384d8 100644 --- a/chapter_10/07_sort.html +++ b/chapter_10/07_sort.html @@ -22,7 +22,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/08_sort_hover.html b/chapter_10/08_sort_hover.html index c8bf393..d89079c 100644 --- a/chapter_10/08_sort_hover.html +++ b/chapter_10/08_sort_hover.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/09_resort.html b/chapter_10/09_resort.html index b6de9f0..446dd9c 100644 --- a/chapter_10/09_resort.html +++ b/chapter_10/09_resort.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/10_delay.html b/chapter_10/10_delay.html index 0d624be..ec3914e 100644 --- a/chapter_10/10_delay.html +++ b/chapter_10/10_delay.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/11_browser_tooltip.html b/chapter_10/11_browser_tooltip.html index 1200168..c5a37f3 100644 --- a/chapter_10/11_browser_tooltip.html +++ b/chapter_10/11_browser_tooltip.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/12_browser_tooltip_text.html b/chapter_10/12_browser_tooltip_text.html index 96f807b..28309af 100644 --- a/chapter_10/12_browser_tooltip_text.html +++ b/chapter_10/12_browser_tooltip_text.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/13_svg_tooltip.html b/chapter_10/13_svg_tooltip.html index 1078de8..3be484e 100644 --- a/chapter_10/13_svg_tooltip.html +++ b/chapter_10/13_svg_tooltip.html @@ -26,7 +26,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_10/14_div_tooltip.html b/chapter_10/14_div_tooltip.html index c4293a1..d658ada 100644 --- a/chapter_10/14_div_tooltip.html +++ b/chapter_10/14_div_tooltip.html @@ -56,7 +56,7 @@ .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, h]); diff --git a/chapter_11/03_stacked_bar.html b/chapter_11/03_stacked_bar.html index 423df18..f7e6ce4 100644 --- a/chapter_11/03_stacked_bar.html +++ b/chapter_11/03_stacked_bar.html @@ -51,7 +51,7 @@ .domain(d3.range(dataset[0].length)) .rangeRoundBands([0, w], 0.05); - var yScale = d3.scale.linear() + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d3.max(d, function(d) { From a3675e2ed06c3474c5619150e50478efc061c19e Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sat, 7 Jan 2017 11:22:14 -0800 Subject: [PATCH 14/85] Lots of updates to work with v4.0 --- chapter_08/01_axes.html | 5 +- chapter_08/02_axes_bottom.html | 19 ++----- chapter_08/03_axes_clean.html | 17 +----- chapter_08/04_axes_y.html | 20 ++----- chapter_08/05_axes_random.html | 20 ++----- chapter_08/06_axes_no_labels.html | 20 ++----- chapter_08/07_axes_format.html | 20 ++----- chapter_09/02_bar_chart_with_scales.html | 9 ++-- chapter_09/03_updates_all_data.html | 9 ++-- chapter_09/04_updates_all_data_fixed.html | 11 ++-- chapter_09/05_transition.html | 11 ++-- chapter_09/06_duration.html | 11 ++-- chapter_09/07_duration_slow.html | 11 ++-- chapter_09/08_duration_slow_labels_fixed.html | 11 ++-- chapter_09/09_ease_linear.html | 15 +++--- chapter_09/10_ease_circle.html | 15 +++--- chapter_09/11_ease_elastic.html | 15 +++--- chapter_09/12_ease_bounce.html | 15 +++--- chapter_09/13_delay_static.html | 11 ++-- chapter_09/14_delay_dynamic.html | 11 ++-- chapter_09/15_delay_dynamic_scaled.html | 11 ++-- chapter_09/16_delay_dynamic_scaled_fewer.html | 11 ++-- chapter_09/17_randomized_data.html | 11 ++-- chapter_09/18_dynamic_scale.html | 11 ++-- chapter_09/19_axes_static.html | 20 ++----- chapter_09/20_axes_dynamic.html | 20 ++----- chapter_09/21_each.html | 32 ++++------- chapter_09/22_each_combo_transition.html | 24 ++------- .../23_each_combo_transition_chained.html | 22 ++------ chapter_09/24_clip-path.html | 24 ++------- chapter_09/25_adding_values.html | 22 ++++---- chapter_09/26_removing_values.html | 22 ++++---- chapter_09/27_data_join_with_key.html | 28 +++++----- chapter_09/28_adding_and_removing.html | 28 +++++----- chapter_09/29_dynamic_labels.html | 53 +++++++++--------- chapter_10/01_start.html | 9 ++-- chapter_10/02_click.html | 9 ++-- chapter_10/03_hover.html | 9 ++-- chapter_10/04_mouseover.html | 9 ++-- chapter_10/05_mouseout.html | 9 ++-- chapter_10/06_smoother.html | 9 ++-- chapter_10/07_sort.html | 9 ++-- chapter_10/08_sort_hover.html | 9 ++-- chapter_10/09_resort.html | 9 ++-- chapter_10/10_delay.html | 9 ++-- chapter_10/11_browser_tooltip.html | 7 +-- chapter_10/12_browser_tooltip_text.html | 7 +-- chapter_10/13_svg_tooltip.html | 9 ++-- chapter_10/14_div_tooltip.html | 9 ++-- chapter_11/01_pie.html | 10 ++-- chapter_11/02_ring.html | 10 ++-- chapter_11/03_stacked_bar.html | 54 ++++++++----------- chapter_11/04_force.html | 51 ++++++++++++++---- 53 files changed, 373 insertions(+), 489 deletions(-) diff --git a/chapter_08/01_axes.html b/chapter_08/01_axes.html index d01a0bb..4b9f1e4 100644 --- a/chapter_08/01_axes.html +++ b/chapter_08/01_axes.html @@ -36,9 +36,8 @@ .range([2, 5]); //Define X axis - var xAxis = d3.svg.axis() - .scale(xScale) - .orient("bottom"); + var xAxis = d3.axisBottom() + .scale(xScale); //Create SVG element var svg = d3.select("body") diff --git a/chapter_08/02_axes_bottom.html b/chapter_08/02_axes_bottom.html index 6376795..c8f2cb8 100644 --- a/chapter_08/02_axes_bottom.html +++ b/chapter_08/02_axes_bottom.html @@ -5,19 +5,7 @@ D3: Axis moved to the bottom @@ -48,9 +36,8 @@ .range([2, 5]); //Define X axis - var xAxis = d3.svg.axis() - .scale(xScale) - .orient("bottom"); + var xAxis = d3.axisBottom() + .scale(xScale); //Create SVG element var svg = d3.select("body") diff --git a/chapter_08/03_axes_clean.html b/chapter_08/03_axes_clean.html index d783818..3f18593 100644 --- a/chapter_08/03_axes_clean.html +++ b/chapter_08/03_axes_clean.html @@ -5,19 +5,7 @@ D3: Axis with fewer ticks @@ -48,9 +36,8 @@ .range([2, 5]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Create SVG element diff --git a/chapter_08/04_axes_y.html b/chapter_08/04_axes_y.html index aed21d2..ed8ad40 100644 --- a/chapter_08/04_axes_y.html +++ b/chapter_08/04_axes_y.html @@ -5,19 +5,7 @@ D3: Vertical axis added @@ -48,15 +36,13 @@ .range([2, 5]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element diff --git a/chapter_08/05_axes_random.html b/chapter_08/05_axes_random.html index 275fa37..19abc40 100644 --- a/chapter_08/05_axes_random.html +++ b/chapter_08/05_axes_random.html @@ -5,19 +5,7 @@ D3: Dynamic axes generated based on min/max values of randomized data @@ -62,15 +50,13 @@ .range([2, 5]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element diff --git a/chapter_08/06_axes_no_labels.html b/chapter_08/06_axes_no_labels.html index 7fd7e28..96ed518 100644 --- a/chapter_08/06_axes_no_labels.html +++ b/chapter_08/06_axes_no_labels.html @@ -5,19 +5,7 @@ D3: Labels removed @@ -62,15 +50,13 @@ .range([2, 5]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element diff --git a/chapter_08/07_axes_format.html b/chapter_08/07_axes_format.html index a52b56a..820786c 100644 --- a/chapter_08/07_axes_format.html +++ b/chapter_08/07_axes_format.html @@ -5,19 +5,7 @@ D3: Test of formatted axis values @@ -64,16 +52,14 @@ var formatAsPercentage = d3.format(".1%"); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5) .tickFormat(formatAsPercentage); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5) .tickFormat(formatAsPercentage); diff --git a/chapter_09/02_bar_chart_with_scales.html b/chapter_09/02_bar_chart_with_scales.html index 645e40e..d0a19e8 100644 --- a/chapter_09/02_bar_chart_with_scales.html +++ b/chapter_09/02_bar_chart_with_scales.html @@ -18,9 +18,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -43,7 +44,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -61,7 +62,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/03_updates_all_data.html b/chapter_09/03_updates_all_data.html index de81d6a..68fd0c7 100644 --- a/chapter_09/03_updates_all_data.html +++ b/chapter_09/03_updates_all_data.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/04_updates_all_data_fixed.html b/chapter_09/04_updates_all_data_fixed.html index d6d18b9..618ff47 100644 --- a/chapter_09/04_updates_all_data_fixed.html +++ b/chapter_09/04_updates_all_data_fixed.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -104,7 +105,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/05_transition.html b/chapter_09/05_transition.html index ba12265..cd62219 100644 --- a/chapter_09/05_transition.html +++ b/chapter_09/05_transition.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -105,7 +106,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/06_duration.html b/chapter_09/06_duration.html index c1402f9..30a3a4e 100644 --- a/chapter_09/06_duration.html +++ b/chapter_09/06_duration.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -106,7 +107,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/07_duration_slow.html b/chapter_09/07_duration_slow.html index 85f15a3..cb26667 100644 --- a/chapter_09/07_duration_slow.html +++ b/chapter_09/07_duration_slow.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -106,7 +107,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/08_duration_slow_labels_fixed.html b/chapter_09/08_duration_slow_labels_fixed.html index 4911c71..01e374b 100644 --- a/chapter_09/08_duration_slow_labels_fixed.html +++ b/chapter_09/08_duration_slow_labels_fixed.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -108,7 +109,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/09_ease_linear.html b/chapter_09/09_ease_linear.html index 1df8f4d..15e772f 100644 --- a/chapter_09/09_ease_linear.html +++ b/chapter_09/09_ease_linear.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -89,7 +90,7 @@ .data(dataset) .transition() .duration(2000) - .ease("linear") + .ease(d3.easeLinear) .attr("y", function(d) { return h - yScale(d); }) @@ -105,12 +106,12 @@ .data(dataset) .transition() .duration(2000) - .ease("linear") + .ease(d3.easeLinear) .text(function(d) { return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/10_ease_circle.html b/chapter_09/10_ease_circle.html index fd6bf78..8b7b7bc 100644 --- a/chapter_09/10_ease_circle.html +++ b/chapter_09/10_ease_circle.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -89,7 +90,7 @@ .data(dataset) .transition() .duration(2000) - .ease("circle") + .ease(d3.easeCircleIn) .attr("y", function(d) { return h - yScale(d); }) @@ -105,12 +106,12 @@ .data(dataset) .transition() .duration(2000) - .ease("circle") + .ease(d3.easeCircleIn) .text(function(d) { return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/11_ease_elastic.html b/chapter_09/11_ease_elastic.html index 2b02150..bdb7c74 100644 --- a/chapter_09/11_ease_elastic.html +++ b/chapter_09/11_ease_elastic.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -89,7 +90,7 @@ .data(dataset) .transition() .duration(2000) - .ease("elastic") + .ease(d3.easeElasticOut) .attr("y", function(d) { return h - yScale(d); }) @@ -105,12 +106,12 @@ .data(dataset) .transition() .duration(2000) - .ease("elastic") + .ease(d3.easeElasticOut) .text(function(d) { return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/12_ease_bounce.html b/chapter_09/12_ease_bounce.html index c32b292..f427db0 100644 --- a/chapter_09/12_ease_bounce.html +++ b/chapter_09/12_ease_bounce.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -89,7 +90,7 @@ .data(dataset) .transition() .duration(2000) - .ease("bounce") + .ease(d3.easeBounceOut) .attr("y", function(d) { return h - yScale(d); }) @@ -105,12 +106,12 @@ .data(dataset) .transition() .duration(2000) - .ease("bounce") + .ease(d3.easeBounceOut) .text(function(d) { return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/13_delay_static.html b/chapter_09/13_delay_static.html index 747290d..1ea4ab8 100644 --- a/chapter_09/13_delay_static.html +++ b/chapter_09/13_delay_static.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -110,7 +111,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/14_delay_dynamic.html b/chapter_09/14_delay_dynamic.html index a29f5ed..33c24f9 100644 --- a/chapter_09/14_delay_dynamic.html +++ b/chapter_09/14_delay_dynamic.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -114,7 +115,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/15_delay_dynamic_scaled.html b/chapter_09/15_delay_dynamic_scaled.html index 70121b1..35e3499 100644 --- a/chapter_09/15_delay_dynamic_scaled.html +++ b/chapter_09/15_delay_dynamic_scaled.html @@ -22,9 +22,10 @@ 11, 12, 15, 20, 18, 17, 16, 18, 23, 25, 25, 16, 10, 18, 19, 14, 11, 15, 18, 19 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -65,7 +66,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -116,7 +117,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/16_delay_dynamic_scaled_fewer.html b/chapter_09/16_delay_dynamic_scaled_fewer.html index 6d45adb..30f33c4 100644 --- a/chapter_09/16_delay_dynamic_scaled_fewer.html +++ b/chapter_09/16_delay_dynamic_scaled_fewer.html @@ -20,9 +20,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -45,7 +46,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -63,7 +64,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -112,7 +113,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/17_randomized_data.html b/chapter_09/17_randomized_data.html index 41560ff..94b6d4e 100644 --- a/chapter_09/17_randomized_data.html +++ b/chapter_09/17_randomized_data.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -118,7 +119,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/18_dynamic_scale.html b/chapter_09/18_dynamic_scale.html index bf8dbca..b218237 100644 --- a/chapter_09/18_dynamic_scale.html +++ b/chapter_09/18_dynamic_scale.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -123,7 +124,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/19_axes_static.html b/chapter_09/19_axes_static.html index c5a95ac..c070691 100644 --- a/chapter_09/19_axes_static.html +++ b/chapter_09/19_axes_static.html @@ -5,19 +5,7 @@ D3: Transitioning points to randomized values @@ -51,15 +39,13 @@ .range([h - padding, padding]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element diff --git a/chapter_09/20_axes_dynamic.html b/chapter_09/20_axes_dynamic.html index 5789aee..217cb22 100644 --- a/chapter_09/20_axes_dynamic.html +++ b/chapter_09/20_axes_dynamic.html @@ -5,19 +5,7 @@ D3: Transitioning points to randomized values, plus rescaled axes! @@ -51,15 +39,13 @@ .range([h - padding, padding]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element diff --git a/chapter_09/21_each.html b/chapter_09/21_each.html index e73552b..3a8a943 100644 --- a/chapter_09/21_each.html +++ b/chapter_09/21_each.html @@ -5,19 +5,7 @@ D3: Using each() to start and end transitions @@ -51,15 +39,13 @@ .range([h - padding, padding]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element @@ -118,7 +104,7 @@ .data(dataset) .transition() .duration(1000) - .each("start", function() { + .on("start", function() { d3.select(this) .attr("fill", "magenta") .attr("r", 3); @@ -129,7 +115,7 @@ .attr("cy", function(d) { return yScale(d[1]); }) - .each("end", function() { + .on("end", function() { d3.select(this) .attr("fill", "black") .attr("r", 2); @@ -137,14 +123,14 @@ //Update X axis svg.select(".x.axis") - .transition() - .duration(1000) + .transition() + .duration(1000) .call(xAxis); //Update Y axis svg.select(".y.axis") - .transition() - .duration(1000) + .transition() + .duration(1000) .call(yAxis); }); diff --git a/chapter_09/22_each_combo_transition.html b/chapter_09/22_each_combo_transition.html index fb030fc..2e8f6b8 100644 --- a/chapter_09/22_each_combo_transition.html +++ b/chapter_09/22_each_combo_transition.html @@ -5,19 +5,7 @@ D3: Using each() to specify two transitions in sequence @@ -51,15 +39,13 @@ .range([h - padding, padding]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element @@ -118,7 +104,7 @@ .data(dataset) .transition() .duration(1000) - .each("start", function() { + .on("start", function() { d3.select(this) .attr("fill", "magenta") .attr("r", 7); @@ -129,7 +115,7 @@ .attr("cy", function(d) { return yScale(d[1]); }) - .each("end", function() { + .on("end", function() { d3.select(this) .transition() .duration(1000) diff --git a/chapter_09/23_each_combo_transition_chained.html b/chapter_09/23_each_combo_transition_chained.html index bafd9e2..df99907 100644 --- a/chapter_09/23_each_combo_transition_chained.html +++ b/chapter_09/23_each_combo_transition_chained.html @@ -5,19 +5,7 @@ D3: Using each() to specify two transitions in sequence @@ -51,15 +39,13 @@ .range([h - padding, padding]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element @@ -118,7 +104,7 @@ .data(dataset) .transition() .duration(1000) - .each("start", function() { + .on("start", function() { d3.select(this) .attr("fill", "magenta") .attr("r", 7); diff --git a/chapter_09/24_clip-path.html b/chapter_09/24_clip-path.html index 6ad6d40..ccb96ea 100644 --- a/chapter_09/24_clip-path.html +++ b/chapter_09/24_clip-path.html @@ -5,19 +5,7 @@ D3: Introducing the clipping path @@ -51,15 +39,13 @@ .range([h - padding, padding]); //Define X axis - var xAxis = d3.svg.axis() + var xAxis = d3.axisBottom() .scale(xScale) - .orient("bottom") .ticks(5); //Define Y axis - var yAxis = d3.svg.axis() + var yAxis = d3.axisLeft() .scale(yScale) - .orient("left") .ticks(5); //Create SVG element @@ -130,7 +116,7 @@ .data(dataset) .transition() .duration(1000) - .each("start", function() { + .on("start", function() { d3.select(this) .attr("fill", "magenta") .attr("r", 7); @@ -141,7 +127,7 @@ .attr("cy", function(d) { return yScale(d[1]); }) - .each("end", function() { + .on("end", function() { d3.select(this) .transition() .duration(1000) diff --git a/chapter_09/25_adding_values.html b/chapter_09/25_adding_values.html index d703fda..50f3ef9 100644 --- a/chapter_09/25_adding_values.html +++ b/chapter_09/25_adding_values.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -101,16 +102,15 @@ .attr("y", function(d) { //Sets the y value, based on the updated yScale return h - yScale(d); }) - .attr("width", xScale.rangeBand()) //Sets the width value, based on the updated xScale + .attr("width", xScale.bandwidth()) //Sets the width value, based on the updated xScale .attr("height", function(d) { //Sets the height value, based on the updated yScale return yScale(d); }) .attr("fill", function(d) { //Sets the fill value return "rgb(0, 0, " + (d * 10) + ")"; - }); - - //Update… - bars.transition() //Initiate a transition on all elements in the update selection (all rects) + }) + .merge(bars) //Update… + .transition() //Initiate a transition on all elements in the update selection (all rects) .duration(500) .attr("x", function(d, i) { //Set new x position, based on the updated xScale return xScale(i); @@ -118,7 +118,7 @@ .attr("y", function(d) { //Set new y position, based on the updated yScale return h - yScale(d); }) - .attr("width", xScale.rangeBand()) //Set new width value, based on the updated xScale + .attr("width", xScale.bandwidth()) //Set new width value, based on the updated xScale .attr("height", function(d) { //Set new height value, based on the updated yScale return yScale(d); }); @@ -137,7 +137,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/26_removing_values.html b/chapter_09/26_removing_values.html index d9a5d8b..263861a 100644 --- a/chapter_09/26_removing_values.html +++ b/chapter_09/26_removing_values.html @@ -21,9 +21,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -46,7 +47,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; @@ -99,16 +100,15 @@ .attr("y", function(d) { //Sets the y value, based on the updated yScale return h - yScale(d); }) - .attr("width", xScale.rangeBand()) //Sets the width value, based on the updated xScale + .attr("width", xScale.bandwidth()) //Sets the width value, based on the updated xScale .attr("height", function(d) { //Sets the height value, based on the updated yScale return yScale(d); }) .attr("fill", function(d) { //Sets the fill value return "rgb(0, 0, " + (d * 10) + ")"; - }); - - //Update… - bars.transition() //Initiate a transition on all elements in the update selection (all rects) + }) + .merge(bars) //Update… + .transition() //Initiate a transition on all elements in the update selection (all rects) .duration(500) .attr("x", function(d, i) { //Set new x position, based on the updated xScale return xScale(i); @@ -116,7 +116,7 @@ .attr("y", function(d) { //Set new y position, based on the updated yScale return h - yScale(d); }) - .attr("width", xScale.rangeBand()) //Set new width value, based on the updated xScale + .attr("width", xScale.bandwidth()) //Set new width value, based on the updated xScale .attr("height", function(d) { //Set new height value, based on the updated yScale return yScale(d); }); @@ -142,7 +142,7 @@ return d; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_09/27_data_join_with_key.html b/chapter_09/27_data_join_with_key.html index 9b3872e..20a986d 100644 --- a/chapter_09/27_data_join_with_key.html +++ b/chapter_09/27_data_join_with_key.html @@ -38,11 +38,12 @@ { key: 17, value: 18 }, { key: 18, value: 23 }, { key: 19, value: 25 } ]; - - var xScale = d3.scale.ordinal() - .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + var xScale = d3.scaleBand() + .domain(d3.range(dataset.length)) + .range([0, w]) + .paddingInner(0.05); + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d.value; })]) .range([0, h]); @@ -69,7 +70,7 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }) @@ -87,7 +88,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d.value) + 14; @@ -121,16 +122,15 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }) .attr("fill", function(d) { return "rgb(0, 0, " + (d.value * 10) + ")"; - }); - - //Update… - bars.transition() + }) + .merge(bars) //Update… + .transition() .duration(500) .attr("x", function(d, i) { return xScale(i); @@ -138,7 +138,7 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }); @@ -147,7 +147,7 @@ bars.exit() .transition() .duration(500) - .attr("x", -xScale.rangeBand()) // <-- Exit stage left + .attr("x", -xScale.bandwidth()) // <-- Exit stage left .remove(); @@ -164,7 +164,7 @@ return d.value; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d.value) + 14; diff --git a/chapter_09/28_adding_and_removing.html b/chapter_09/28_adding_and_removing.html index 4761dec..e4b3aad 100644 --- a/chapter_09/28_adding_and_removing.html +++ b/chapter_09/28_adding_and_removing.html @@ -40,10 +40,11 @@ { key: 18, value: 23 }, { key: 19, value: 25 } ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); - + .range([0, w]) + .paddingInner(0.05); + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d.value; })]) .range([0, h]); @@ -70,7 +71,7 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }) @@ -88,7 +89,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d.value) + 14; @@ -138,16 +139,15 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }) .attr("fill", function(d) { return "rgb(0, 0, " + (d.value * 10) + ")"; - }); - - //Update… - bars.transition() + }) + .merge(bars) //Update… + .transition() .duration(500) .attr("x", function(d, i) { return xScale(i); @@ -155,7 +155,7 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }); @@ -164,14 +164,14 @@ bars.exit() .transition() .duration(500) - .attr("x", -xScale.rangeBand()) + .attr("x", -xScale.bandwidth()) .remove(); //Update all labels // - //Exercise: Modify this code to remove the correct label each time! + //Exercise: Modify this code to add and remove the correct labels each time! // svg.selectAll("text") .data(dataset, key) @@ -181,7 +181,7 @@ return d.value; }) .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d.value) + 14; diff --git a/chapter_09/29_dynamic_labels.html b/chapter_09/29_dynamic_labels.html index 9cf7c8d..8e76927 100644 --- a/chapter_09/29_dynamic_labels.html +++ b/chapter_09/29_dynamic_labels.html @@ -40,10 +40,11 @@ { key: 18, value: 23 }, { key: 19, value: 25 } ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); - + .range([0, w]) + .paddingInner(0.05); + var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d.value; })]) .range([0, h]); @@ -70,7 +71,7 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }) @@ -88,7 +89,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d.value) + 14; @@ -138,16 +139,15 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }) .attr("fill", function(d) { return "rgb(0, 0, " + (d.value * 10) + ")"; - }); - - //Update… - bars.transition() + }) + .merge(bars) //Update… + .transition() .duration(500) .attr("x", function(d, i) { return xScale(i); @@ -155,7 +155,7 @@ .attr("y", function(d) { return h - yScale(d.value); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d.value); }); @@ -164,7 +164,7 @@ bars.exit() .transition() .duration(500) - .attr("x", -xScale.rangeBand()) + .attr("x", -xScale.bandwidth()) .remove(); @@ -174,6 +174,13 @@ //Select… var labels = svg.selectAll("text") .data(dataset, key); + + //Exit… + labels.exit() + .transition() + .duration(500) + .attr("x", -xScale.bandwidth()) + .remove(); //Enter… labels.enter() @@ -188,21 +195,13 @@ }) .attr("font-family", "sans-serif") .attr("font-size", "11px") - .attr("fill", "white"); - - //Update… - labels.transition() - .duration(500) - .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; - }); - - //Exit… - labels.exit() - .transition() - .duration(500) - .attr("x", -xScale.rangeBand()) - .remove(); + .attr("fill", "white") + .merge(labels) //Update… + .transition() + .duration(500) + .attr("x", function(d, i) { + return xScale(i) + xScale.bandwidth() / 2; + }); }); diff --git a/chapter_10/01_start.html b/chapter_10/01_start.html index 147e573..f20570d 100644 --- a/chapter_10/01_start.html +++ b/chapter_10/01_start.html @@ -18,9 +18,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -43,7 +44,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -61,7 +62,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/02_click.html b/chapter_10/02_click.html index 043f95f..46e4206 100644 --- a/chapter_10/02_click.html +++ b/chapter_10/02_click.html @@ -18,9 +18,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -43,7 +44,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -64,7 +65,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/03_hover.html b/chapter_10/03_hover.html index 8366387..7ec0589 100644 --- a/chapter_10/03_hover.html +++ b/chapter_10/03_hover.html @@ -22,9 +22,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -65,7 +66,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/04_mouseover.html b/chapter_10/04_mouseover.html index 3f7759e..0c57a14 100644 --- a/chapter_10/04_mouseover.html +++ b/chapter_10/04_mouseover.html @@ -18,9 +18,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -43,7 +44,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -65,7 +66,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/05_mouseout.html b/chapter_10/05_mouseout.html index 86162f8..7f390d2 100644 --- a/chapter_10/05_mouseout.html +++ b/chapter_10/05_mouseout.html @@ -18,9 +18,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -43,7 +44,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -69,7 +70,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/06_smoother.html b/chapter_10/06_smoother.html index b124d77..3525ad4 100644 --- a/chapter_10/06_smoother.html +++ b/chapter_10/06_smoother.html @@ -18,9 +18,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -43,7 +44,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -71,7 +72,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/07_sort.html b/chapter_10/07_sort.html index 05384d8..8fce17b 100644 --- a/chapter_10/07_sort.html +++ b/chapter_10/07_sort.html @@ -18,9 +18,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -43,7 +44,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -74,7 +75,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/08_sort_hover.html b/chapter_10/08_sort_hover.html index d89079c..0abc88b 100644 --- a/chapter_10/08_sort_hover.html +++ b/chapter_10/08_sort_hover.html @@ -22,9 +22,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -68,7 +69,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/09_resort.html b/chapter_10/09_resort.html index 446dd9c..674bae4 100644 --- a/chapter_10/09_resort.html +++ b/chapter_10/09_resort.html @@ -22,9 +22,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -68,7 +69,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/10_delay.html b/chapter_10/10_delay.html index ec3914e..0395512 100644 --- a/chapter_10/10_delay.html +++ b/chapter_10/10_delay.html @@ -22,9 +22,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -68,7 +69,7 @@ }) .attr("text-anchor", "middle") .attr("x", function(d, i) { - return xScale(i) + xScale.rangeBand() / 2; + return xScale(i) + xScale.bandwidth() / 2; }) .attr("y", function(d) { return h - yScale(d) + 14; diff --git a/chapter_10/11_browser_tooltip.html b/chapter_10/11_browser_tooltip.html index c5a37f3..4be0fc2 100644 --- a/chapter_10/11_browser_tooltip.html +++ b/chapter_10/11_browser_tooltip.html @@ -22,9 +22,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) diff --git a/chapter_10/12_browser_tooltip_text.html b/chapter_10/12_browser_tooltip_text.html index 28309af..4ac0400 100644 --- a/chapter_10/12_browser_tooltip_text.html +++ b/chapter_10/12_browser_tooltip_text.html @@ -22,9 +22,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) diff --git a/chapter_10/13_svg_tooltip.html b/chapter_10/13_svg_tooltip.html index 3be484e..63a0f02 100644 --- a/chapter_10/13_svg_tooltip.html +++ b/chapter_10/13_svg_tooltip.html @@ -22,9 +22,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -47,7 +48,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -57,7 +58,7 @@ .on("mouseover", function(d) { //Get this bar's x/y values, then augment for the tooltip - var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.rangeBand() / 2; + var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.bandwidth() / 2; var yPosition = parseFloat(d3.select(this).attr("y")) + 14; //Create the tooltip label diff --git a/chapter_10/14_div_tooltip.html b/chapter_10/14_div_tooltip.html index d658ada..f16095a 100644 --- a/chapter_10/14_div_tooltip.html +++ b/chapter_10/14_div_tooltip.html @@ -52,9 +52,10 @@ var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; - var xScale = d3.scale.ordinal() + var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .rangeRoundBands([0, w], 0.05); + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) @@ -77,7 +78,7 @@ .attr("y", function(d) { return h - yScale(d); }) - .attr("width", xScale.rangeBand()) + .attr("width", xScale.bandwidth()) .attr("height", function(d) { return yScale(d); }) @@ -87,7 +88,7 @@ .on("mouseover", function(d) { //Get this bar's x/y values, then augment for the tooltip - var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.rangeBand() / 2; + var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.bandwidth() / 2; var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + h / 2; //Update the tooltip position and value diff --git a/chapter_11/01_pie.html b/chapter_11/01_pie.html index 99f87a9..23c0a4d 100644 --- a/chapter_11/01_pie.html +++ b/chapter_11/01_pie.html @@ -25,14 +25,14 @@ var outerRadius = w / 2; var innerRadius = 0; - var arc = d3.svg.arc() - .innerRadius(innerRadius) - .outerRadius(outerRadius); + var arc = d3.arc() + .innerRadius(innerRadius) + .outerRadius(outerRadius); - var pie = d3.layout.pie(); + var pie = d3.pie(); //Easy colors accessible via a 10-step ordinal scale - var color = d3.scale.category10(); + var color = d3.scaleOrdinal(d3.schemeCategory10); //Create SVG element var svg = d3.select("body") diff --git a/chapter_11/02_ring.html b/chapter_11/02_ring.html index 8705e0d..eb493d9 100644 --- a/chapter_11/02_ring.html +++ b/chapter_11/02_ring.html @@ -25,14 +25,14 @@ var outerRadius = w / 2; var innerRadius = w / 3; - var arc = d3.svg.arc() - .innerRadius(innerRadius) - .outerRadius(outerRadius); + var arc = d3.arc() + .innerRadius(innerRadius) + .outerRadius(outerRadius); - var pie = d3.layout.pie(); + var pie = d3.pie(); //Easy colors accessible via a 10-step ordinal scale - var color = d3.scale.category10(); + var color = d3.scaleOrdinal(d3.schemeCategory10); //Create SVG element var svg = d3.select("body") diff --git a/chapter_11/03_stacked_bar.html b/chapter_11/03_stacked_bar.html index f7e6ce4..7c80f54 100644 --- a/chapter_11/03_stacked_bar.html +++ b/chapter_11/03_stacked_bar.html @@ -17,52 +17,40 @@ //Original data var dataset = [ - [ - { x: 0, y: 5 }, - { x: 1, y: 4 }, - { x: 2, y: 2 }, - { x: 3, y: 7 }, - { x: 4, y: 23 } - ], - [ - { x: 0, y: 10 }, - { x: 1, y: 12 }, - { x: 2, y: 19 }, - { x: 3, y: 23 }, - { x: 4, y: 17 } - ], - [ - { x: 0, y: 22 }, - { x: 1, y: 28 }, - { x: 2, y: 32 }, - { x: 3, y: 35 }, - { x: 4, y: 43 } - ] + { apples: 5, oranges: 10, grapes: 22 }, + { apples: 4, oranges: 12, grapes: 28 }, + { apples: 2, oranges: 19, grapes: 32 }, + { apples: 7, oranges: 23, grapes: 35 }, + { apples: 23, oranges: 17, grapes: 43 } ]; //Set up stack method - var stack = d3.layout.stack(); + var stack = d3.stack() + .keys([ "apples", "oranges", "grapes" ]) + .order(d3.stackOrderNone) + .offset(d3.stackOffsetNone); //Data, stacked - stack(dataset); + var series = stack(dataset); //Set up scales - var xScale = d3.scale.ordinal() - .domain(d3.range(dataset[0].length)) - .rangeRoundBands([0, w], 0.05); + var xScale = d3.scaleBand() + .domain(d3.range(dataset.length)) + .range([0, w]) + .paddingInner(0.05); var yScale = d3.scaleLinear() .domain([0, - d3.max(dataset, function(d) { + d3.max(series, function(d) { return d3.max(d, function(d) { - return d.y0 + d.y; + return d[0] + d[1]; }); }) ]) .range([0, h]); //Easy colors accessible via a 10-step ordinal scale - var colors = d3.scale.category10(); + var colors = d3.scaleOrdinal(d3.schemeCategory10); //Create SVG element var svg = d3.select("body") @@ -72,7 +60,7 @@ // Add a group for each row of data var groups = svg.selectAll("g") - .data(dataset) + .data(series) .enter() .append("g") .style("fill", function(d, i) { @@ -88,12 +76,12 @@ return xScale(i); }) .attr("y", function(d) { - return yScale(d.y0); + return yScale(d[0]); }) .attr("height", function(d) { - return yScale(d.y); + return yScale(d[1]); }) - .attr("width", xScale.rangeBand()); + .attr("width", xScale.bandwidth()); diff --git a/chapter_11/04_force.html b/chapter_11/04_force.html index 6c3c918..31e5db5 100644 --- a/chapter_11/04_force.html +++ b/chapter_11/04_force.html @@ -47,15 +47,22 @@ }; //Initialize a default force layout, using the nodes and edges in dataset - var force = d3.layout.force() - .nodes(dataset.nodes) - .links(dataset.edges) - .size([w, h]) - .linkDistance([50]) - .charge([-100]) - .start(); + // var force = d3.forceSimulation() + // .nodes(dataset.nodes) + // .links(dataset.edges) + // .size([w, h]) + // .linkDistance([50]) + // .charge([-100]) + // .start(); - var colors = d3.scale.category10(); + + var force = d3.forceSimulation(dataset.nodes) + .force("charge", d3.forceManyBody()) + .force("link", d3.forceLink(dataset.edges)) + .force("center", d3.forceCenter().x(w/2).y(h/2)); + + + var colors = d3.scaleOrdinal(d3.schemeCategory10); //Create SVG element var svg = d3.select("body") @@ -80,7 +87,16 @@ .style("fill", function(d, i) { return colors(i); }) - .call(force.drag); + .call(d3.drag() + .on("start", dragstarted) + .on("drag", dragged) + .on("end", dragended)); + + //Add a simple tooltip + nodes.append("title") + .text(function(d) { + return d.name; + }); //Every time the simulation "ticks", this will be called force.on("tick", function() { @@ -96,6 +112,23 @@ }); +function dragstarted(d) { + if (!d3.event.active) force.alphaTarget(0.3).restart(); + d.fx = d.x; + d.fy = d.y; +} + +function dragged(d) { + d.fx = d3.event.x; + d.fy = d3.event.y; +} + +function dragended(d) { + if (!d3.event.active) force.alphaTarget(0); + d.fx = null; + d.fy = null; +} + \ No newline at end of file From 1fd877c666d6e0daa523bf7db40a6c778179ad5a Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 20 Jan 2017 11:11:04 -0800 Subject: [PATCH 15/85] All examples updated to work with v4, yaaaaay --- chapter_11/04_force_basic.html | 103 ++++++++++++++++++ ...{04_force.html => 04_force_draggable.html} | 41 +++---- chapter_12/01_paths.html | 4 +- chapter_12/02_projection.html | 4 +- chapter_12/03_scaled.html | 4 +- chapter_12/04_fill.html | 4 +- chapter_12/05_choropleth.html | 6 +- chapter_12/06_points.html | 6 +- chapter_12/07_points_sized.html | 6 +- chapter_12/08_oceans.html | 4 +- chapter_12/09_mercator.html | 6 +- 11 files changed, 141 insertions(+), 47 deletions(-) create mode 100644 chapter_11/04_force_basic.html rename chapter_11/{04_force.html => 04_force_draggable.html} (83%) diff --git a/chapter_11/04_force_basic.html b/chapter_11/04_force_basic.html new file mode 100644 index 0000000..9e678bb --- /dev/null +++ b/chapter_11/04_force_basic.html @@ -0,0 +1,103 @@ + + + + + D3: Force layout + + + + + + + \ No newline at end of file diff --git a/chapter_11/04_force.html b/chapter_11/04_force_draggable.html similarity index 83% rename from chapter_11/04_force.html rename to chapter_11/04_force_draggable.html index 31e5db5..264058d 100644 --- a/chapter_11/04_force.html +++ b/chapter_11/04_force_draggable.html @@ -47,15 +47,6 @@ }; //Initialize a default force layout, using the nodes and edges in dataset - // var force = d3.forceSimulation() - // .nodes(dataset.nodes) - // .links(dataset.edges) - // .size([w, h]) - // .linkDistance([50]) - // .charge([-100]) - // .start(); - - var force = d3.forceSimulation(dataset.nodes) .force("charge", d3.forceManyBody()) .force("link", d3.forceLink(dataset.edges)) @@ -87,7 +78,7 @@ .style("fill", function(d, i) { return colors(i); }) - .call(d3.drag() + .call(d3.drag() //Define what to do on drag events .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); @@ -111,23 +102,23 @@ }); + //Define drag event functions + function dragstarted(d) { + if (!d3.event.active) force.alphaTarget(0.3).restart(); + d.fx = d.x; + d.fy = d.y; + } -function dragstarted(d) { - if (!d3.event.active) force.alphaTarget(0.3).restart(); - d.fx = d.x; - d.fy = d.y; -} - -function dragged(d) { - d.fx = d3.event.x; - d.fy = d3.event.y; -} + function dragged(d) { + d.fx = d3.event.x; + d.fy = d3.event.y; + } -function dragended(d) { - if (!d3.event.active) force.alphaTarget(0); - d.fx = null; - d.fy = null; -} + function dragended(d) { + if (!d3.event.active) force.alphaTarget(0); + d.fx = null; + d.fy = null; + } diff --git a/chapter_12/01_paths.html b/chapter_12/01_paths.html index b2fc6a1..49cb926 100644 --- a/chapter_12/01_paths.html +++ b/chapter_12/01_paths.html @@ -15,8 +15,8 @@ var w = 500; var h = 300; - //Define default path generator - var path = d3.geo.path(); + //Define path generator, using the Albers USA projection + var path = d3.geoPath(d3.geoAlbersUsa()); //Create SVG element var svg = d3.select("body") diff --git a/chapter_12/02_projection.html b/chapter_12/02_projection.html index 06e7593..57db383 100644 --- a/chapter_12/02_projection.html +++ b/chapter_12/02_projection.html @@ -16,11 +16,11 @@ var h = 300; //Define map projection - var projection = d3.geo.albersUsa() + var projection = d3.geoAlbersUsa() .translate([w/2, h/2]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Create SVG element diff --git a/chapter_12/03_scaled.html b/chapter_12/03_scaled.html index 24595e8..92deb0c 100644 --- a/chapter_12/03_scaled.html +++ b/chapter_12/03_scaled.html @@ -16,12 +16,12 @@ var h = 300; //Define map projection - var projection = d3.geo.albersUsa() + var projection = d3.geoAlbersUsa() .translate([w/2, h/2]) .scale([500]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Create SVG element diff --git a/chapter_12/04_fill.html b/chapter_12/04_fill.html index c058d51..a853fef 100644 --- a/chapter_12/04_fill.html +++ b/chapter_12/04_fill.html @@ -16,12 +16,12 @@ var h = 300; //Define map projection - var projection = d3.geo.albersUsa() + var projection = d3.geoAlbersUsa() .translate([w/2, h/2]) .scale([500]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Create SVG element diff --git a/chapter_12/05_choropleth.html b/chapter_12/05_choropleth.html index c232581..8000d6e 100644 --- a/chapter_12/05_choropleth.html +++ b/chapter_12/05_choropleth.html @@ -16,16 +16,16 @@ var h = 300; //Define map projection - var projection = d3.geo.albersUsa() + var projection = d3.geoAlbersUsa() .translate([w/2, h/2]) .scale([500]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Define quantize scale to sort data values into buckets of color - var color = d3.scale.quantize() + var color = d3.scaleQuantize() .range(["rgb(237,248,233)","rgb(186,228,179)","rgb(116,196,118)","rgb(49,163,84)","rgb(0,109,44)"]); //Colors taken from colorbrewer.js, included in the D3 download diff --git a/chapter_12/06_points.html b/chapter_12/06_points.html index 079633c..67c4065 100644 --- a/chapter_12/06_points.html +++ b/chapter_12/06_points.html @@ -16,16 +16,16 @@ var h = 300; //Define map projection - var projection = d3.geo.albersUsa() + var projection = d3.geoAlbersUsa() .translate([w/2, h/2]) .scale([500]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Define quantize scale to sort data values into buckets of color - var color = d3.scale.quantize() + var color = d3.scaleQuantize() .range(["rgb(237,248,233)","rgb(186,228,179)","rgb(116,196,118)","rgb(49,163,84)","rgb(0,109,44)"]); //Colors taken from colorbrewer.js, included in the D3 download diff --git a/chapter_12/07_points_sized.html b/chapter_12/07_points_sized.html index c137bce..1162b3c 100644 --- a/chapter_12/07_points_sized.html +++ b/chapter_12/07_points_sized.html @@ -16,16 +16,16 @@ var h = 300; //Define map projection - var projection = d3.geo.albersUsa() + var projection = d3.geoAlbersUsa() .translate([w/2, h/2]) .scale([500]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Define quantize scale to sort data values into buckets of color - var color = d3.scale.quantize() + var color = d3.scaleQuantize() .range(["rgb(237,248,233)","rgb(186,228,179)","rgb(116,196,118)","rgb(49,163,84)","rgb(0,109,44)"]); //Colors taken from colorbrewer.js, included in the D3 download diff --git a/chapter_12/08_oceans.html b/chapter_12/08_oceans.html index 3ad93bb..723262b 100644 --- a/chapter_12/08_oceans.html +++ b/chapter_12/08_oceans.html @@ -16,12 +16,12 @@ var h = 300; //Define map projection - var projection = d3.geo.albersUsa() + var projection = d3.geoAlbersUsa() .translate([w/2, h/2]) .scale([500]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Create SVG element diff --git a/chapter_12/09_mercator.html b/chapter_12/09_mercator.html index 509cf93..9b17625 100644 --- a/chapter_12/09_mercator.html +++ b/chapter_12/09_mercator.html @@ -16,12 +16,12 @@ var h = 300; //Define map projection - var projection = d3.geo.mercator() + var projection = d3.geoMercator() .translate([w/2, h/2]) - .scale([500]); + .scale([w * 0.16]); //Define path generator - var path = d3.geo.path() + var path = d3.geoPath() .projection(projection); //Create SVG element From 4114bb0227d99ce9a87d615000d33bc9e286b077 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 26 Jan 2017 14:35:48 -0800 Subject: [PATCH 16/85] Updated to D3 4.4.4 and simplified file path --- chapter_04/01_empty_page_template.html | 2 +- chapter_05/01_empty_page_template.html | 2 +- chapter_05/02_new_element.html | 2 +- chapter_05/03_csv_loading_example.html | 2 +- chapter_05/04_creating_paragraphs.html | 2 +- chapter_05/05_creating_paragraphs_text.html | 2 +- .../06_creating_paragraphs_counting.html | 2 +- .../07_creating_paragraphs_with_style.html | 2 +- ...ating_paragraphs_with_style_functions.html | 2 +- chapter_06/01_drawing_divs.html | 2 +- chapter_06/02_drawing_divs_height.html | 2 +- chapter_06/03_drawing_divs_spaced.html | 2 +- chapter_06/04_power_of_data.html | 2 +- chapter_06/05_power_of_data_more_points.html | 2 +- chapter_06/06_power_of_data_random.html | 2 +- chapter_06/07_power_of_data_rounded.html | 2 +- chapter_06/08_drawing_svgs.html | 2 +- chapter_06/09_drawing_svgs_size.html | 2 +- chapter_06/10_drawing_svgs_circles.html | 2 +- chapter_06/11_drawing_svgs_color.html | 2 +- chapter_06/12_making_a_bar_chart_divs.html | 2 +- chapter_06/13_making_a_bar_chart_rects.html | 2 +- chapter_06/14_making_a_bar_chart_offset.html | 2 +- chapter_06/15_making_a_bar_chart_even.html | 2 +- chapter_06/16_making_a_bar_chart_widths.html | 2 +- chapter_06/17_making_a_bar_chart_heights.html | 2 +- chapter_06/18_making_a_bar_chart_teal.html | 2 +- chapter_06/19_making_a_bar_chart_blues.html | 2 +- chapter_06/20_making_a_bar_chart_labels.html | 2 +- chapter_06/21_making_a_bar_chart_aligned.html | 2 +- chapter_06/22_scatterplot.html | 2 +- chapter_06/23_scatterplot_sqrt.html | 2 +- chapter_06/24_scatterplot_labels.html | 2 +- chapter_07/01_scale_test.html | 2 +- chapter_07/02_scaled_plot.html | 2 +- chapter_07/03_scaled_plot_inverted.html | 2 +- chapter_07/04_scaled_plot_padding.html | 2 +- chapter_07/05_scaled_plot_radii.html | 2 +- chapter_07/06_scaled_plot_big.html | 2 +- chapter_07/07_scaled_plot_large.html | 2 +- chapter_08/01_axes.html | 2 +- chapter_08/02_axes_bottom.html | 2 +- chapter_08/03_axes_clean.html | 2 +- chapter_08/04_axes_y.html | 2 +- chapter_08/05_axes_random.html | 2 +- chapter_08/06_axes_no_labels.html | 2 +- chapter_08/07_axes_format.html | 2 +- chapter_09/01_bar_chart.html | 2 +- chapter_09/02_bar_chart_with_scales.html | 2 +- chapter_09/03_updates_all_data.html | 2 +- chapter_09/04_updates_all_data_fixed.html | 2 +- chapter_09/05_transition.html | 2 +- chapter_09/06_duration.html | 2 +- chapter_09/07_duration_slow.html | 2 +- chapter_09/08_duration_slow_labels_fixed.html | 2 +- chapter_09/09_ease_linear.html | 2 +- chapter_09/10_ease_circle.html | 2 +- chapter_09/11_ease_elastic.html | 2 +- chapter_09/12_ease_bounce.html | 2 +- chapter_09/13_delay_static.html | 2 +- chapter_09/14_delay_dynamic.html | 2 +- chapter_09/15_delay_dynamic_scaled.html | 2 +- chapter_09/16_delay_dynamic_scaled_fewer.html | 2 +- chapter_09/17_randomized_data.html | 2 +- chapter_09/18_dynamic_scale.html | 2 +- chapter_09/19_axes_static.html | 2 +- chapter_09/20_axes_dynamic.html | 2 +- chapter_09/21_each.html | 2 +- chapter_09/22_each_combo_transition.html | 2 +- .../23_each_combo_transition_chained.html | 2 +- chapter_09/24_clip-path.html | 2 +- chapter_09/25_adding_values.html | 2 +- chapter_09/26_removing_values.html | 2 +- chapter_09/27_data_join_with_key.html | 2 +- chapter_09/28_adding_and_removing.html | 2 +- chapter_09/29_dynamic_labels.html | 2 +- chapter_10/01_start.html | 2 +- chapter_10/02_click.html | 2 +- chapter_10/03_hover.html | 2 +- chapter_10/04_mouseover.html | 2 +- chapter_10/05_mouseout.html | 2 +- chapter_10/06_smoother.html | 2 +- chapter_10/07_sort.html | 2 +- chapter_10/08_sort_hover.html | 2 +- chapter_10/09_resort.html | 2 +- chapter_10/10_delay.html | 2 +- chapter_10/11_browser_tooltip.html | 2 +- chapter_10/12_browser_tooltip_text.html | 2 +- chapter_10/13_svg_tooltip.html | 2 +- chapter_10/14_div_tooltip.html | 2 +- chapter_11/01_pie.html | 2 +- chapter_11/02_ring.html | 2 +- chapter_11/03_stacked_bar.html | 2 +- chapter_11/04_force_basic.html | 2 +- chapter_11/04_force_draggable.html | 2 +- chapter_12/01_paths.html | 2 +- chapter_12/02_projection.html | 2 +- chapter_12/03_scaled.html | 2 +- chapter_12/04_fill.html | 2 +- chapter_12/05_choropleth.html | 2 +- chapter_12/06_points.html | 2 +- chapter_12/07_points_sized.html | 2 +- chapter_12/08_oceans.html | 2 +- chapter_12/09_mercator.html | 2 +- d3/d3.v4.js => d3.js | 26052 ++++++++-------- 105 files changed, 13135 insertions(+), 13125 deletions(-) rename d3/d3.v4.js => d3.js (92%) diff --git a/chapter_04/01_empty_page_template.html b/chapter_04/01_empty_page_template.html index 078bb51..730548d 100644 --- a/chapter_04/01_empty_page_template.html +++ b/chapter_04/01_empty_page_template.html @@ -3,7 +3,7 @@ D3 Page Template - + + + + + + + + + + diff --git a/chapter_06/09_drawing_svgs_size.html b/chapter_06/09_drawing_svgs_size.html index 6edacf9..fd16d3d 100644 --- a/chapter_06/09_drawing_svgs_size.html +++ b/chapter_06/09_drawing_svgs_size.html @@ -3,7 +3,7 @@ D3: Putting the SVG's width and height into variables - + diff --git a/chapter_06/10_drawing_svgs_circles.html b/chapter_06/10_drawing_svgs_circles.html index 2fb46d1..2c73b47 100644 --- a/chapter_06/10_drawing_svgs_circles.html +++ b/chapter_06/10_drawing_svgs_circles.html @@ -3,7 +3,7 @@ D3: Drawing SVG circles with data - + diff --git a/chapter_06/11_drawing_svgs_color.html b/chapter_06/11_drawing_svgs_color.html index e3713b0..d9018b5 100644 --- a/chapter_06/11_drawing_svgs_color.html +++ b/chapter_06/11_drawing_svgs_color.html @@ -3,7 +3,7 @@ D3: Using color in SVG - + diff --git a/chapter_06/12_making_a_bar_chart_divs.html b/chapter_06/12_making_a_bar_chart_divs.html index 2051ee2..44a84c2 100644 --- a/chapter_06/12_making_a_bar_chart_divs.html +++ b/chapter_06/12_making_a_bar_chart_divs.html @@ -3,7 +3,7 @@ D3: A bar chart with divs - + diff --git a/chapter_06/14_making_a_bar_chart_offset.html b/chapter_06/14_making_a_bar_chart_offset.html index 9c1d55a..a743d94 100644 --- a/chapter_06/14_making_a_bar_chart_offset.html +++ b/chapter_06/14_making_a_bar_chart_offset.html @@ -3,7 +3,7 @@ D3: Making a bar chart with SVG rects, spacing - + diff --git a/chapter_06/15_making_a_bar_chart_even.html b/chapter_06/15_making_a_bar_chart_even.html index 57acbbf..145ab84 100644 --- a/chapter_06/15_making_a_bar_chart_even.html +++ b/chapter_06/15_making_a_bar_chart_even.html @@ -3,7 +3,7 @@ D3: Making a bar chart with SVG rects, evenly spaced - + diff --git a/chapter_06/16_making_a_bar_chart_widths.html b/chapter_06/16_making_a_bar_chart_widths.html index c1ce632..2d9d9c5 100644 --- a/chapter_06/16_making_a_bar_chart_widths.html +++ b/chapter_06/16_making_a_bar_chart_widths.html @@ -3,7 +3,7 @@ D3: Making a bar chart with SVG rects, dynamic widths and spacing - + diff --git a/chapter_06/17_making_a_bar_chart_heights.html b/chapter_06/17_making_a_bar_chart_heights.html index faf636a..cdc71e5 100644 --- a/chapter_06/17_making_a_bar_chart_heights.html +++ b/chapter_06/17_making_a_bar_chart_heights.html @@ -3,7 +3,7 @@ D3: A true bar chart with SVG rects - + diff --git a/chapter_06/18_making_a_bar_chart_teal.html b/chapter_06/18_making_a_bar_chart_teal.html index afeac96..f94ea33 100644 --- a/chapter_06/18_making_a_bar_chart_teal.html +++ b/chapter_06/18_making_a_bar_chart_teal.html @@ -3,7 +3,7 @@ D3: Adding color to an SVG bar chart - + diff --git a/chapter_06/19_making_a_bar_chart_blues.html b/chapter_06/19_making_a_bar_chart_blues.html index 53d887f..af9628d 100644 --- a/chapter_06/19_making_a_bar_chart_blues.html +++ b/chapter_06/19_making_a_bar_chart_blues.html @@ -3,7 +3,7 @@ D3: Adding dynamic color, based on data - + diff --git a/chapter_06/20_making_a_bar_chart_labels.html b/chapter_06/20_making_a_bar_chart_labels.html index 58d35ea..fc5a312 100644 --- a/chapter_06/20_making_a_bar_chart_labels.html +++ b/chapter_06/20_making_a_bar_chart_labels.html @@ -3,7 +3,7 @@ D3: SVG bar chart with value labels - + diff --git a/chapter_06/21_making_a_bar_chart_aligned.html b/chapter_06/21_making_a_bar_chart_aligned.html index e8e0188..f59d669 100644 --- a/chapter_06/21_making_a_bar_chart_aligned.html +++ b/chapter_06/21_making_a_bar_chart_aligned.html @@ -3,7 +3,7 @@ D3: SVG bar chart with value labels (centered) - + diff --git a/chapter_06/22_scatterplot.html b/chapter_06/22_scatterplot.html index 490dc10..061eea7 100644 --- a/chapter_06/22_scatterplot.html +++ b/chapter_06/22_scatterplot.html @@ -3,7 +3,7 @@ D3: A simple scatterplot with SVG - + diff --git a/chapter_06/23_scatterplot_sqrt.html b/chapter_06/23_scatterplot_sqrt.html index 5873669..1af1076 100644 --- a/chapter_06/23_scatterplot_sqrt.html +++ b/chapter_06/23_scatterplot_sqrt.html @@ -3,7 +3,7 @@ D3: A simple scatterplot, setting radii from data - + diff --git a/chapter_06/24_scatterplot_labels.html b/chapter_06/24_scatterplot_labels.html index bac10f6..8649989 100644 --- a/chapter_06/24_scatterplot_labels.html +++ b/chapter_06/24_scatterplot_labels.html @@ -3,7 +3,7 @@ D3: A simple scatterplot with value labels - + diff --git a/chapter_07/01_scale_test.html b/chapter_07/01_scale_test.html index 28f44c0..19b75f3 100644 --- a/chapter_07/01_scale_test.html +++ b/chapter_07/01_scale_test.html @@ -3,7 +3,7 @@ D3: Empty page for testing scale functions - + diff --git a/chapter_07/02_scaled_plot.html b/chapter_07/02_scaled_plot.html index 0c8b8f0..145b580 100644 --- a/chapter_07/02_scaled_plot.html +++ b/chapter_07/02_scaled_plot.html @@ -3,7 +3,7 @@ D3: Linear scales with a scatterplot - + diff --git a/chapter_07/03_scaled_plot_inverted.html b/chapter_07/03_scaled_plot_inverted.html index e6ca0c4..e6febe4 100644 --- a/chapter_07/03_scaled_plot_inverted.html +++ b/chapter_07/03_scaled_plot_inverted.html @@ -3,7 +3,7 @@ D3: An inverted linear scale - + diff --git a/chapter_07/04_scaled_plot_padding.html b/chapter_07/04_scaled_plot_padding.html index fc3a9b7..f08d344 100644 --- a/chapter_07/04_scaled_plot_padding.html +++ b/chapter_07/04_scaled_plot_padding.html @@ -3,7 +3,7 @@ D3: Adding padding to the scatterplot - + diff --git a/chapter_07/05_scaled_plot_radii.html b/chapter_07/05_scaled_plot_radii.html index d3971d7..6b279d2 100644 --- a/chapter_07/05_scaled_plot_radii.html +++ b/chapter_07/05_scaled_plot_radii.html @@ -3,7 +3,7 @@ D3: Adjusted radii - + diff --git a/chapter_07/06_scaled_plot_big.html b/chapter_07/06_scaled_plot_big.html index 3d770ae..d4f3408 100644 --- a/chapter_07/06_scaled_plot_big.html +++ b/chapter_07/06_scaled_plot_big.html @@ -3,7 +3,7 @@ D3: Scaled scatterplot, with new (large) data value added - + diff --git a/chapter_07/07_scaled_plot_large.html b/chapter_07/07_scaled_plot_large.html index f62972f..67eaaeb 100644 --- a/chapter_07/07_scaled_plot_large.html +++ b/chapter_07/07_scaled_plot_large.html @@ -3,7 +3,7 @@ D3: Scaled scatterplot, resized to be bigger! - + diff --git a/chapter_08/01_axes.html b/chapter_08/01_axes.html index 4b9f1e4..68f76e4 100644 --- a/chapter_08/01_axes.html +++ b/chapter_08/01_axes.html @@ -3,7 +3,7 @@ D3: A simple, unstyled axis - + diff --git a/chapter_08/02_axes_bottom.html b/chapter_08/02_axes_bottom.html index c8f2cb8..b0f493a 100644 --- a/chapter_08/02_axes_bottom.html +++ b/chapter_08/02_axes_bottom.html @@ -3,7 +3,7 @@ D3: Axis moved to the bottom - + diff --git a/chapter_08/03_axes_clean.html b/chapter_08/03_axes_clean.html index 3f18593..7497482 100644 --- a/chapter_08/03_axes_clean.html +++ b/chapter_08/03_axes_clean.html @@ -3,7 +3,7 @@ D3: Axis with fewer ticks - + diff --git a/chapter_08/04_axes_y.html b/chapter_08/04_axes_y.html index ed8ad40..d9d6f71 100644 --- a/chapter_08/04_axes_y.html +++ b/chapter_08/04_axes_y.html @@ -3,7 +3,7 @@ D3: Vertical axis added - + diff --git a/chapter_08/05_axes_random.html b/chapter_08/05_axes_random.html index 19abc40..492d9f3 100644 --- a/chapter_08/05_axes_random.html +++ b/chapter_08/05_axes_random.html @@ -3,7 +3,7 @@ D3: Dynamic axes generated based on min/max values of randomized data - + diff --git a/chapter_08/06_axes_no_labels.html b/chapter_08/06_axes_no_labels.html index 96ed518..b26a9f5 100644 --- a/chapter_08/06_axes_no_labels.html +++ b/chapter_08/06_axes_no_labels.html @@ -3,7 +3,7 @@ D3: Labels removed - + diff --git a/chapter_08/07_axes_format.html b/chapter_08/07_axes_format.html index 820786c..fb8b042 100644 --- a/chapter_08/07_axes_format.html +++ b/chapter_08/07_axes_format.html @@ -3,7 +3,7 @@ D3: Test of formatted axis values - + diff --git a/chapter_09/01_bar_chart.html b/chapter_09/01_bar_chart.html index 4b322e3..d976ad4 100644 --- a/chapter_09/01_bar_chart.html +++ b/chapter_09/01_bar_chart.html @@ -3,7 +3,7 @@ D3: A simple bar chart - + diff --git a/chapter_09/02_bar_chart_with_scales.html b/chapter_09/02_bar_chart_with_scales.html index d0a19e8..631716b 100644 --- a/chapter_09/02_bar_chart_with_scales.html +++ b/chapter_09/02_bar_chart_with_scales.html @@ -3,7 +3,7 @@ D3: A flexible, scalable bar chart - + diff --git a/chapter_09/03_updates_all_data.html b/chapter_09/03_updates_all_data.html index 68fd0c7..21e26e8 100644 --- a/chapter_09/03_updates_all_data.html +++ b/chapter_09/03_updates_all_data.html @@ -3,7 +3,7 @@ D3: A bar chart whose data updates with new data - + diff --git a/chapter_09/04_updates_all_data_fixed.html b/chapter_09/04_updates_all_data_fixed.html index 618ff47..24afc26 100644 --- a/chapter_09/04_updates_all_data_fixed.html +++ b/chapter_09/04_updates_all_data_fixed.html @@ -3,7 +3,7 @@ D3: A bar chart whose data updates with new data (labels, too) - + diff --git a/chapter_09/05_transition.html b/chapter_09/05_transition.html index cd62219..5458dde 100644 --- a/chapter_09/05_transition.html +++ b/chapter_09/05_transition.html @@ -3,7 +3,7 @@ D3: A bar chart that transitions to new data! - + diff --git a/chapter_09/06_duration.html b/chapter_09/06_duration.html index 30a3a4e..78d45f5 100644 --- a/chapter_09/06_duration.html +++ b/chapter_09/06_duration.html @@ -3,7 +3,7 @@ D3: A chart transition with controlled duration - + diff --git a/chapter_09/07_duration_slow.html b/chapter_09/07_duration_slow.html index cb26667..bcff852 100644 --- a/chapter_09/07_duration_slow.html +++ b/chapter_09/07_duration_slow.html @@ -3,7 +3,7 @@ D3: A chart transition with controlled duration (slower) - + diff --git a/chapter_09/08_duration_slow_labels_fixed.html b/chapter_09/08_duration_slow_labels_fixed.html index 01e374b..e5d439a 100644 --- a/chapter_09/08_duration_slow_labels_fixed.html +++ b/chapter_09/08_duration_slow_labels_fixed.html @@ -3,7 +3,7 @@ D3: A chart transition with controlled duration (labels, too!) - + diff --git a/chapter_09/09_ease_linear.html b/chapter_09/09_ease_linear.html index 15e772f..8aa2137 100644 --- a/chapter_09/09_ease_linear.html +++ b/chapter_09/09_ease_linear.html @@ -3,7 +3,7 @@ D3: Demo of linear easing - + diff --git a/chapter_09/10_ease_circle.html b/chapter_09/10_ease_circle.html index 8b7b7bc..c553c72 100644 --- a/chapter_09/10_ease_circle.html +++ b/chapter_09/10_ease_circle.html @@ -3,7 +3,7 @@ D3: Demo of circle easing - + diff --git a/chapter_09/11_ease_elastic.html b/chapter_09/11_ease_elastic.html index bdb7c74..6c25476 100644 --- a/chapter_09/11_ease_elastic.html +++ b/chapter_09/11_ease_elastic.html @@ -3,7 +3,7 @@ D3: Demo of elastic easing - + diff --git a/chapter_09/12_ease_bounce.html b/chapter_09/12_ease_bounce.html index f427db0..c9ea3ef 100644 --- a/chapter_09/12_ease_bounce.html +++ b/chapter_09/12_ease_bounce.html @@ -3,7 +3,7 @@ D3: Demo of bounce easing - + diff --git a/chapter_09/13_delay_static.html b/chapter_09/13_delay_static.html index 1ea4ab8..287a7c1 100644 --- a/chapter_09/13_delay_static.html +++ b/chapter_09/13_delay_static.html @@ -3,7 +3,7 @@ D3: A static delay before transition - + diff --git a/chapter_09/14_delay_dynamic.html b/chapter_09/14_delay_dynamic.html index 33c24f9..bd8cd4f 100644 --- a/chapter_09/14_delay_dynamic.html +++ b/chapter_09/14_delay_dynamic.html @@ -3,7 +3,7 @@ D3: A dynamic, per-element delay before transition - + diff --git a/chapter_09/15_delay_dynamic_scaled.html b/chapter_09/15_delay_dynamic_scaled.html index 35e3499..97b47c2 100644 --- a/chapter_09/15_delay_dynamic_scaled.html +++ b/chapter_09/15_delay_dynamic_scaled.html @@ -3,7 +3,7 @@ D3: A dynamic delay, with more elements - + diff --git a/chapter_09/16_delay_dynamic_scaled_fewer.html b/chapter_09/16_delay_dynamic_scaled_fewer.html index 30f33c4..6ee7eb3 100644 --- a/chapter_09/16_delay_dynamic_scaled_fewer.html +++ b/chapter_09/16_delay_dynamic_scaled_fewer.html @@ -3,7 +3,7 @@ D3: A dynamic delay, with fewer elements - + diff --git a/chapter_09/17_randomized_data.html b/chapter_09/17_randomized_data.html index 94b6d4e..28a3b8b 100644 --- a/chapter_09/17_randomized_data.html +++ b/chapter_09/17_randomized_data.html @@ -3,7 +3,7 @@ D3: Transitioning to randomized data values - + diff --git a/chapter_09/18_dynamic_scale.html b/chapter_09/18_dynamic_scale.html index b218237..310d82f 100644 --- a/chapter_09/18_dynamic_scale.html +++ b/chapter_09/18_dynamic_scale.html @@ -3,7 +3,7 @@ D3: Dynamically adjusting the vertical scale - + diff --git a/chapter_09/19_axes_static.html b/chapter_09/19_axes_static.html index c070691..e47958a 100644 --- a/chapter_09/19_axes_static.html +++ b/chapter_09/19_axes_static.html @@ -3,7 +3,7 @@ D3: Transitioning points to randomized values - + diff --git a/chapter_09/20_axes_dynamic.html b/chapter_09/20_axes_dynamic.html index 217cb22..5eac73e 100644 --- a/chapter_09/20_axes_dynamic.html +++ b/chapter_09/20_axes_dynamic.html @@ -3,7 +3,7 @@ D3: Transitioning points to randomized values, plus rescaled axes! - + diff --git a/chapter_09/21_each.html b/chapter_09/21_each.html index 3a8a943..47ca336 100644 --- a/chapter_09/21_each.html +++ b/chapter_09/21_each.html @@ -3,7 +3,7 @@ D3: Using each() to start and end transitions - + diff --git a/chapter_09/22_each_combo_transition.html b/chapter_09/22_each_combo_transition.html index 2e8f6b8..9c53a49 100644 --- a/chapter_09/22_each_combo_transition.html +++ b/chapter_09/22_each_combo_transition.html @@ -3,7 +3,7 @@ D3: Using each() to specify two transitions in sequence - + diff --git a/chapter_09/23_each_combo_transition_chained.html b/chapter_09/23_each_combo_transition_chained.html index df99907..ee9151d 100644 --- a/chapter_09/23_each_combo_transition_chained.html +++ b/chapter_09/23_each_combo_transition_chained.html @@ -3,7 +3,7 @@ D3: Using each() to specify two transitions in sequence - + diff --git a/chapter_09/24_clip-path.html b/chapter_09/24_clip-path.html index ccb96ea..f5a8a8d 100644 --- a/chapter_09/24_clip-path.html +++ b/chapter_09/24_clip-path.html @@ -3,7 +3,7 @@ D3: Introducing the clipping path - + diff --git a/chapter_09/25_adding_values.html b/chapter_09/25_adding_values.html index 50f3ef9..2d01f35 100644 --- a/chapter_09/25_adding_values.html +++ b/chapter_09/25_adding_values.html @@ -3,7 +3,7 @@ D3: Adding values and elements to a chart - + diff --git a/chapter_09/26_removing_values.html b/chapter_09/26_removing_values.html index 263861a..56905fd 100644 --- a/chapter_09/26_removing_values.html +++ b/chapter_09/26_removing_values.html @@ -3,7 +3,7 @@ D3: Removing values from a chart - + diff --git a/chapter_09/27_data_join_with_key.html b/chapter_09/27_data_join_with_key.html index 20a986d..2e5f004 100644 --- a/chapter_09/27_data_join_with_key.html +++ b/chapter_09/27_data_join_with_key.html @@ -3,7 +3,7 @@ D3: Removing values from a chart - + diff --git a/chapter_09/28_adding_and_removing.html b/chapter_09/28_adding_and_removing.html index e4b3aad..d94c149 100644 --- a/chapter_09/28_adding_and_removing.html +++ b/chapter_09/28_adding_and_removing.html @@ -3,7 +3,7 @@ D3: Adding and removing values from a chart - + diff --git a/chapter_09/29_dynamic_labels.html b/chapter_09/29_dynamic_labels.html index 8e76927..d2bca25 100644 --- a/chapter_09/29_dynamic_labels.html +++ b/chapter_09/29_dynamic_labels.html @@ -3,7 +3,7 @@ D3: Adding and removing values from a chart (dynamic labels included) - + diff --git a/chapter_10/01_start.html b/chapter_10/01_start.html index f20570d..8133c24 100644 --- a/chapter_10/01_start.html +++ b/chapter_10/01_start.html @@ -3,7 +3,7 @@ D3: A starting point for interactivity - + diff --git a/chapter_10/02_click.html b/chapter_10/02_click.html index 46e4206..c6a6b71 100644 --- a/chapter_10/02_click.html +++ b/chapter_10/02_click.html @@ -3,7 +3,7 @@ D3: Click to log the data values to the console - + diff --git a/chapter_10/03_hover.html b/chapter_10/03_hover.html index 7ec0589..c790223 100644 --- a/chapter_10/03_hover.html +++ b/chapter_10/03_hover.html @@ -3,7 +3,7 @@ D3: A simple CSS-only hover effect - + diff --git a/chapter_10/05_mouseout.html b/chapter_10/05_mouseout.html index 7f390d2..266af56 100644 --- a/chapter_10/05_mouseout.html +++ b/chapter_10/05_mouseout.html @@ -3,7 +3,7 @@ D3: Using D3 to change fill color on mouseover AND mouseout - + diff --git a/chapter_10/06_smoother.html b/chapter_10/06_smoother.html index 3525ad4..f27ce10 100644 --- a/chapter_10/06_smoother.html +++ b/chapter_10/06_smoother.html @@ -3,7 +3,7 @@ D3: Smoother highlight transitions - + diff --git a/chapter_10/07_sort.html b/chapter_10/07_sort.html index 8fce17b..a36447c 100644 --- a/chapter_10/07_sort.html +++ b/chapter_10/07_sort.html @@ -3,7 +3,7 @@ D3: Sorting visual elements - + diff --git a/chapter_10/08_sort_hover.html b/chapter_10/08_sort_hover.html index 0abc88b..95ff9ae 100644 --- a/chapter_10/08_sort_hover.html +++ b/chapter_10/08_sort_hover.html @@ -3,7 +3,7 @@ D3: Sorting visual elements, with CSS-only hover highlight - + diff --git a/chapter_11/04_force_basic.html b/chapter_11/04_force_basic.html index 9e678bb..006a91c 100644 --- a/chapter_11/04_force_basic.html +++ b/chapter_11/04_force_basic.html @@ -3,7 +3,7 @@ D3: Force layout - + diff --git a/chapter_11/04_force_draggable.html b/chapter_11/04_force_draggable.html index 264058d..2a292f5 100644 --- a/chapter_11/04_force_draggable.html +++ b/chapter_11/04_force_draggable.html @@ -3,7 +3,7 @@ D3: Force layout - + diff --git a/chapter_12/01_paths.html b/chapter_12/01_paths.html index 49cb926..eef4e2d 100644 --- a/chapter_12/01_paths.html +++ b/chapter_12/01_paths.html @@ -3,7 +3,7 @@ D3: Loading GeoJSON data and generating SVG paths - + diff --git a/chapter_12/02_projection.html b/chapter_12/02_projection.html index 57db383..0ef7077 100644 --- a/chapter_12/02_projection.html +++ b/chapter_12/02_projection.html @@ -3,7 +3,7 @@ D3: Applying a projection to SVG paths - + diff --git a/chapter_12/03_scaled.html b/chapter_12/03_scaled.html index 92deb0c..30ca78e 100644 --- a/chapter_12/03_scaled.html +++ b/chapter_12/03_scaled.html @@ -3,7 +3,7 @@ D3: Scaling the AlbersUSA projection - + diff --git a/chapter_12/04_fill.html b/chapter_12/04_fill.html index a853fef..eff1c6a 100644 --- a/chapter_12/04_fill.html +++ b/chapter_12/04_fill.html @@ -3,7 +3,7 @@ D3: Setting path fills - + diff --git a/chapter_12/05_choropleth.html b/chapter_12/05_choropleth.html index 8000d6e..0e61f22 100644 --- a/chapter_12/05_choropleth.html +++ b/chapter_12/05_choropleth.html @@ -3,7 +3,7 @@ D3: Setting path fills dynamically to generate a choropleth - + diff --git a/chapter_12/06_points.html b/chapter_12/06_points.html index 67c4065..0b97c33 100644 --- a/chapter_12/06_points.html +++ b/chapter_12/06_points.html @@ -3,7 +3,7 @@ D3: Adding data points (circles) to the map - + diff --git a/chapter_12/07_points_sized.html b/chapter_12/07_points_sized.html index 1162b3c..2fcfbb3 100644 --- a/chapter_12/07_points_sized.html +++ b/chapter_12/07_points_sized.html @@ -3,7 +3,7 @@ D3: Scaling the circles by data value - + diff --git a/chapter_12/08_oceans.html b/chapter_12/08_oceans.html index 723262b..385da3b 100644 --- a/chapter_12/08_oceans.html +++ b/chapter_12/08_oceans.html @@ -3,7 +3,7 @@ D3: Loading oceans GeoJSON data - + diff --git a/chapter_12/09_mercator.html b/chapter_12/09_mercator.html index 9b17625..50aa5f4 100644 --- a/chapter_12/09_mercator.html +++ b/chapter_12/09_mercator.html @@ -3,7 +3,7 @@ D3: Mercator projection applied to oceans - + diff --git a/d3/d3.v4.js b/d3.js similarity index 92% rename from d3/d3.v4.js rename to d3.js index acc598c..b860f74 100644 --- a/d3/d3.v4.js +++ b/d3.js @@ -1,11 +1,11 @@ -// https://d3js.org Version 4.3.0. Copyright 2016 Mike Bostock. +// https://d3js.org Version 4.4.4. Copyright 2017 Mike Bostock. (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.d3 = global.d3 || {}))); + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); }(this, (function (exports) { 'use strict'; -var version = "4.3.0"; +var version = "4.4.4"; var ascending = function(a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; @@ -123,7 +123,7 @@ var array = Array.prototype; var slice = array.slice; var map = array.map; -var constant$1 = function(x) { +var constant = function(x) { return function() { return x; }; @@ -133,7 +133,7 @@ var identity = function(x) { return x; }; -var range = function(start, stop, step) { +var sequence = function(start, stop, step) { start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; var i = -1, @@ -153,7 +153,7 @@ var e2 = Math.sqrt(2); var ticks = function(start, stop, count) { var step = tickStep(start, stop, count); - return range( + return sequence( Math.ceil(start / step) * step, Math.floor(stop / step) * step + step / 2, // inclusive step @@ -224,15 +224,15 @@ var histogram = function() { } histogram.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant$1(_), histogram) : value; + return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; }; histogram.domain = function(_) { - return arguments.length ? (domain = typeof _ === "function" ? _ : constant$1([_[0], _[1]]), histogram) : domain; + return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; }; histogram.thresholds = function(_) { - return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant$1(slice.call(_)) : constant$1(_), histogram) : threshold; + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; }; return histogram; @@ -432,15572 +432,15582 @@ var zip = function() { return transpose(arguments); }; -var prefix = "$"; - -function Map() {} +var slice$1 = Array.prototype.slice; -Map.prototype = map$1.prototype = { - constructor: Map, - has: function(key) { - return (prefix + key) in this; - }, - get: function(key) { - return this[prefix + key]; - }, - set: function(key, value) { - this[prefix + key] = value; - return this; - }, - remove: function(key) { - var property = prefix + key; - return property in this && delete this[property]; - }, - clear: function() { - for (var property in this) if (property[0] === prefix) delete this[property]; - }, - keys: function() { - var keys = []; - for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); - return keys; - }, - values: function() { - var values = []; - for (var property in this) if (property[0] === prefix) values.push(this[property]); - return values; - }, - entries: function() { - var entries = []; - for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); - return entries; - }, - size: function() { - var size = 0; - for (var property in this) if (property[0] === prefix) ++size; - return size; - }, - empty: function() { - for (var property in this) if (property[0] === prefix) return false; - return true; - }, - each: function(f) { - for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); - } +var identity$1 = function(x) { + return x; }; -function map$1(object, f) { - var map = new Map; - - // Copy constructor. - if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); - - // Index array by numeric index or specified key function. - else if (Array.isArray(object)) { - var i = -1, - n = object.length, - o; - - if (f == null) while (++i < n) map.set(i, object[i]); - else while (++i < n) map.set(f(o = object[i], i, object), o); - } +var top = 1; +var right = 2; +var bottom = 3; +var left = 4; +var epsilon = 1e-6; - // Convert object to map. - else if (object) for (var key in object) map.set(key, object[key]); +function translateX(scale0, scale1, d) { + var x = scale0(d); + return "translate(" + (isFinite(x) ? x : scale1(d)) + ",0)"; +} - return map; +function translateY(scale0, scale1, d) { + var y = scale0(d); + return "translate(0," + (isFinite(y) ? y : scale1(d)) + ")"; } -var nest = function() { - var keys = [], - sortKeys = [], - sortValues, - rollup, - nest; +function center(scale) { + var offset = scale.bandwidth() / 2; + if (scale.round()) offset = Math.round(offset); + return function(d) { + return scale(d) + offset; + }; +} - function apply(array, depth, createResult, setResult) { - if (depth >= keys.length) return rollup != null - ? rollup(array) : (sortValues != null - ? array.sort(sortValues) - : array); +function entering() { + return !this.__axis; +} - var i = -1, - n = array.length, - key = keys[depth++], - keyValue, - value, - valuesByKey = map$1(), - values, - result = createResult(); +function axis(orient, scale) { + var tickArguments = [], + tickValues = null, + tickFormat = null, + tickSizeInner = 6, + tickSizeOuter = 6, + tickPadding = 3; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { - values.push(value); - } else { - valuesByKey.set(keyValue, [value]); - } - } + function axis(context) { + var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, + format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat, + spacing = Math.max(tickSizeInner, 0) + tickPadding, + transform = orient === top || orient === bottom ? translateX : translateY, + range = scale.range(), + range0 = range[0] + 0.5, + range1 = range[range.length - 1] + 0.5, + position = (scale.bandwidth ? center : identity$1)(scale.copy()), + selection = context.selection ? context.selection() : context, + path = selection.selectAll(".domain").data([null]), + tick = selection.selectAll(".tick").data(values, scale).order(), + tickExit = tick.exit(), + tickEnter = tick.enter().append("g").attr("class", "tick"), + line = tick.select("line"), + text = tick.select("text"), + k = orient === top || orient === left ? -1 : 1, + x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x"); - valuesByKey.each(function(values, key) { - setResult(result, key, apply(values, depth, createResult, setResult)); - }); + path = path.merge(path.enter().insert("path", ".tick") + .attr("class", "domain") + .attr("stroke", "#000")); - return result; - } + tick = tick.merge(tickEnter); - function entries(map, depth) { - if (++depth > keys.length) return map; - var array, sortKey = sortKeys[depth - 1]; - if (rollup != null && depth >= keys.length) array = map.entries(); - else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); - return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; - } + line = line.merge(tickEnter.append("line") + .attr("stroke", "#000") + .attr(x + "2", k * tickSizeInner) + .attr(y + "1", 0.5) + .attr(y + "2", 0.5)); - return nest = { - object: function(array) { return apply(array, 0, createObject, setObject); }, - map: function(array) { return apply(array, 0, createMap, setMap); }, - entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, - key: function(d) { keys.push(d); return nest; }, - sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, - sortValues: function(order) { sortValues = order; return nest; }, - rollup: function(f) { rollup = f; return nest; } - }; -}; + text = text.merge(tickEnter.append("text") + .attr("fill", "#000") + .attr(x, k * spacing) + .attr(y, 0.5) + .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); -function createObject() { - return {}; -} + if (context !== selection) { + path = path.transition(context); + tick = tick.transition(context); + line = line.transition(context); + text = text.transition(context); -function setObject(object, key, value) { - object[key] = value; -} + tickExit = tickExit.transition(context) + .attr("opacity", epsilon) + .attr("transform", function(d) { return transform(position, this.parentNode.__axis || position, d); }); -function createMap() { - return map$1(); -} + tickEnter + .attr("opacity", epsilon) + .attr("transform", function(d) { return transform(this.parentNode.__axis || position, position, d); }); + } -function setMap(map, key, value) { - map.set(key, value); -} + tickExit.remove(); -function Set() {} + path + .attr("d", orient === left || orient == right + ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter + : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter); -var proto = map$1.prototype; + tick + .attr("opacity", 1) + .attr("transform", function(d) { return transform(position, position, d); }); -Set.prototype = set.prototype = { - constructor: Set, - has: proto.has, - add: function(value) { - value += ""; - this[prefix + value] = value; - return this; - }, - remove: proto.remove, - clear: proto.clear, - values: proto.keys, - size: proto.size, - empty: proto.empty, - each: proto.each -}; + line + .attr(x + "2", k * tickSizeInner); -function set(object, f) { - var set = new Set; + text + .attr(x, k * spacing) + .text(format); - // Copy constructor. - if (object instanceof Set) object.each(function(value) { set.add(value); }); + selection.filter(entering) + .attr("fill", "none") + .attr("font-size", 10) + .attr("font-family", "sans-serif") + .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); - // Otherwise, assume it’s an array. - else if (object) { - var i = -1, n = object.length; - if (f == null) while (++i < n) set.add(object[i]); - else while (++i < n) set.add(f(object[i], i, object)); + selection + .each(function() { this.__axis = position; }); } - return set; -} + axis.scale = function(_) { + return arguments.length ? (scale = _, axis) : scale; + }; -var keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; -}; + axis.ticks = function() { + return tickArguments = slice$1.call(arguments), axis; + }; -var values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; -}; - -var entries = function(map) { - var entries = []; - for (var key in map) entries.push({key: key, value: map[key]}); - return entries; -}; - -var uniform = function(min, max) { - min = min == null ? 0 : +min; - max = max == null ? 1 : +max; - if (arguments.length === 1) max = min, min = 0; - else max -= min; - return function() { - return Math.random() * max + min; + axis.tickArguments = function(_) { + return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice(); }; -}; - -var normal = function(mu, sigma) { - var x, r; - mu = mu == null ? 0 : +mu; - sigma = sigma == null ? 1 : +sigma; - return function() { - var y; - - // If available, use the second previously-generated uniform random. - if (x != null) y = x, x = null; - // Otherwise, generate a new x and y. - else do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); + axis.tickValues = function(_) { + return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice(); + }; - return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); + axis.tickFormat = function(_) { + return arguments.length ? (tickFormat = _, axis) : tickFormat; }; -}; -var logNormal = function() { - var randomNormal = normal.apply(this, arguments); - return function() { - return Math.exp(randomNormal()); + axis.tickSize = function(_) { + return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; }; -}; -var irwinHall = function(n) { - return function() { - for (var sum = 0, i = 0; i < n; ++i) sum += Math.random(); - return sum; + axis.tickSizeInner = function(_) { + return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; }; -}; -var bates = function(n) { - var randomIrwinHall = irwinHall(n); - return function() { - return randomIrwinHall() / n; + axis.tickSizeOuter = function(_) { + return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; }; -}; -var exponential = function(lambda) { - return function() { - return -Math.log(1 - Math.random()) / lambda; + axis.tickPadding = function(_) { + return arguments.length ? (tickPadding = +_, axis) : tickPadding; }; -}; -function linear(t) { - return +t; + return axis; } -function quadIn(t) { - return t * t; +function axisTop(scale) { + return axis(top, scale); } -function quadOut(t) { - return t * (2 - t); +function axisRight(scale) { + return axis(right, scale); } -function quadInOut(t) { - return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; +function axisBottom(scale) { + return axis(bottom, scale); } -function cubicIn(t) { - return t * t * t; +function axisLeft(scale) { + return axis(left, scale); } -function cubicOut(t) { - return --t * t * t + 1; -} +var noop = {value: function() {}}; -function cubicInOut(t) { - return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; +function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); } -var exponent = 3; - -var polyIn = (function custom(e) { - e = +e; +function Dispatch(_) { + this._ = _; +} - function polyIn(t) { - return Math.pow(t, e); - } +function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); +} - polyIn.exponent = custom; +Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; - return polyIn; -})(exponent); + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; + return; + } -var polyOut = (function custom(e) { - e = +e; + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); + else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); + } - function polyOut(t) { - return 1 - Math.pow(1 - t, e); + return this; + }, + copy: function() { + var copy = {}, _ = this._; + for (var t in _) copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function(type, that) { + if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + }, + apply: function(type, that, args) { + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); } +}; - polyOut.exponent = custom; - - return polyOut; -})(exponent); - -var polyInOut = (function custom(e) { - e = +e; - - function polyInOut(t) { - return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; +function get(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } } +} - polyInOut.exponent = custom; +function set(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) type.push({name: name, value: callback}); + return type; +} - return polyInOut; -})(exponent); +var xhtml = "http://www.w3.org/1999/xhtml"; -var pi = Math.PI; -var halfPi = pi / 2; +var namespaces = { + svg: "http://www.w3.org/2000/svg", + xhtml: xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" +}; -function sinIn(t) { - return 1 - Math.cos(t * halfPi); -} +var namespace = function(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; +}; -function sinOut(t) { - return Math.sin(t * halfPi); +function creatorInherit(name) { + return function() { + var document = this.ownerDocument, + uri = this.namespaceURI; + return uri === xhtml && document.documentElement.namespaceURI === xhtml + ? document.createElement(name) + : document.createElementNS(uri, name); + }; } -function sinInOut(t) { - return (1 - Math.cos(pi * t)) / 2; +function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; } -function expIn(t) { - return Math.pow(2, 10 * t - 10); -} +var creator = function(name) { + var fullname = namespace(name); + return (fullname.local + ? creatorFixed + : creatorInherit)(fullname); +}; -function expOut(t) { - return 1 - Math.pow(2, -10 * t); -} +var nextId = 0; -function expInOut(t) { - return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; +function local$1() { + return new Local; } -function circleIn(t) { - return 1 - Math.sqrt(1 - t * t); +function Local() { + this._ = "@" + (++nextId).toString(36); } -function circleOut(t) { - return Math.sqrt(1 - --t * t); -} +Local.prototype = local$1.prototype = { + constructor: Local, + get: function(node) { + var id = this._; + while (!(id in node)) if (!(node = node.parentNode)) return; + return node[id]; + }, + set: function(node, value) { + return node[this._] = value; + }, + remove: function(node) { + return this._ in node && delete node[this._]; + }, + toString: function() { + return this._; + } +}; -function circleInOut(t) { - return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; +var matcher = function(selector) { + return function() { + return this.matches(selector); + }; +}; + +if (typeof document !== "undefined") { + var element = document.documentElement; + if (!element.matches) { + var vendorMatches = element.webkitMatchesSelector + || element.msMatchesSelector + || element.mozMatchesSelector + || element.oMatchesSelector; + matcher = function(selector) { + return function() { + return vendorMatches.call(this, selector); + }; + }; + } } -var b1 = 4 / 11; -var b2 = 6 / 11; -var b3 = 8 / 11; -var b4 = 3 / 4; -var b5 = 9 / 11; -var b6 = 10 / 11; -var b7 = 15 / 16; -var b8 = 21 / 22; -var b9 = 63 / 64; -var b0 = 1 / b1 / b1; +var matcher$1 = matcher; -function bounceIn(t) { - return 1 - bounceOut(1 - t); +var filterEvents = {}; + +exports.event = null; + +if (typeof document !== "undefined") { + var element$1 = document.documentElement; + if (!("onmouseenter" in element$1)) { + filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; + } } -function bounceOut(t) { - return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; +function filterContextListener(listener, index, group) { + listener = contextListener(listener, index, group); + return function(event) { + var related = event.relatedTarget; + if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { + listener.call(this, event); + } + }; } -function bounceInOut(t) { - return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; +function contextListener(listener, index, group) { + return function(event1) { + var event0 = exports.event; // Events can be reentrant (e.g., focus). + exports.event = event1; + try { + listener.call(this, this.__data__, index, group); + } finally { + exports.event = event0; + } + }; } -var overshoot = 1.70158; +function parseTypenames$1(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + return {type: t, name: name}; + }); +} -var backIn = (function custom(s) { - s = +s; +function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) return; + for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + } else { + on[++i] = o; + } + } + if (++i) on.length = i; + else delete this.__on; + }; +} - function backIn(t) { - return t * t * ((s + 1) * t - s); - } +function onAdd(typename, value, capture) { + var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; + return function(d, i, group) { + var on = this.__on, o, listener = wrap(value, i, group); + if (on) for (var j = 0, m = on.length; j < m; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + this.addEventListener(o.type, o.listener = listener, o.capture = capture); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, capture); + o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; + if (!on) this.__on = [o]; + else on.push(o); + }; +} - backIn.overshoot = custom; +var selection_on = function(typename, value, capture) { + var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; - return backIn; -})(overshoot); + if (arguments.length < 2) { + var on = this.node().__on; + if (on) for (var j = 0, m = on.length, o; j < m; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } -var backOut = (function custom(s) { - s = +s; + on = value ? onAdd : onRemove; + if (capture == null) capture = false; + for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); + return this; +}; - function backOut(t) { - return --t * t * ((s + 1) * t + s) + 1; +function customEvent(event1, listener, that, args) { + var event0 = exports.event; + event1.sourceEvent = exports.event; + exports.event = event1; + try { + return listener.apply(that, args); + } finally { + exports.event = event0; } +} - backOut.overshoot = custom; - - return backOut; -})(overshoot); +var sourceEvent = function() { + var current = exports.event, source; + while (source = current.sourceEvent) current = source; + return current; +}; -var backInOut = (function custom(s) { - s = +s; +var point = function(node, event) { + var svg = node.ownerSVGElement || node; - function backInOut(t) { - return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; } - backInOut.overshoot = custom; + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; +}; - return backInOut; -})(overshoot); +var mouse = function(node) { + var event = sourceEvent(); + if (event.changedTouches) event = event.changedTouches[0]; + return point(node, event); +}; -var tau = 2 * Math.PI; -var amplitude = 1; -var period = 0.3; +function none() {} -var elasticIn = (function custom(a, p) { - var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); +var selector = function(selector) { + return selector == null ? none : function() { + return this.querySelector(selector); + }; +}; - function elasticIn(t) { - return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); +var selection_select = function(select) { + if (typeof select !== "function") select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } } - elasticIn.amplitude = function(a) { return custom(a, p * tau); }; - elasticIn.period = function(p) { return custom(a, p); }; + return new Selection(subgroups, this._parents); +}; - return elasticIn; -})(amplitude, period); +function empty$1() { + return []; +} -var elasticOut = (function custom(a, p) { - var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); +var selectorAll = function(selector) { + return selector == null ? empty$1 : function() { + return this.querySelectorAll(selector); + }; +}; - function elasticOut(t) { - return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); - } +var selection_selectAll = function(select) { + if (typeof select !== "function") select = selectorAll(select); - elasticOut.amplitude = function(a) { return custom(a, p * tau); }; - elasticOut.period = function(p) { return custom(a, p); }; + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } - return elasticOut; -})(amplitude, period); + return new Selection(subgroups, parents); +}; -var elasticInOut = (function custom(a, p) { - var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); +var selection_filter = function(match) { + if (typeof match !== "function") match = matcher$1(match); - function elasticInOut(t) { - return ((t = t * 2 - 1) < 0 - ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) - : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } } - elasticInOut.amplitude = function(a) { return custom(a, p * tau); }; - elasticInOut.period = function(p) { return custom(a, p); }; - - return elasticInOut; -})(amplitude, period); + return new Selection(subgroups, this._parents); +}; -var area = function(polygon) { - var i = -1, - n = polygon.length, - a, - b = polygon[n - 1], - area = 0; +var sparse = function(update) { + return new Array(update.length); +}; - while (++i < n) { - a = b; - b = polygon[i]; - area += a[1] * b[0] - a[0] * b[1]; - } - - return area / 2; +var selection_enter = function() { + return new Selection(this._enter || this._groups.map(sparse), this._parents); }; -var centroid = function(polygon) { - var i = -1, - n = polygon.length, - x = 0, - y = 0, - a, - b = polygon[n - 1], - c, - k = 0; - - while (++i < n) { - a = b; - b = polygon[i]; - k += c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; - } +function EnterNode(parent, datum) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum; +} - return k *= 3, [x / k, y / k]; +EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, + insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, + querySelector: function(selector) { return this._parent.querySelector(selector); }, + querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } }; -// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of -// the 3D cross product in a quadrant I Cartesian coordinate system (+x is -// right, +y is up). Returns a positive value if ABC is counter-clockwise, -// negative if clockwise, and zero if the points are collinear. -var cross = function(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); +var constant$1 = function(x) { + return function() { + return x; + }; }; -function lexicographicOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; +var keyPrefix = "$"; // Protect against keys like “__proto__”. + +function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, + node, + groupLength = group.length, + dataLength = data.length; + + // Put any non-null nodes that fit into update. + // Put any null nodes into enter. + // Put any remaining data into enter. + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Put any non-null nodes that don’t fit into exit. + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } } -// Computes the upper convex hull per the monotone chain algorithm. -// Assumes points.length >= 3, is sorted by x, unique in y. -// Returns an array of indices into points in left-to-right order. -function computeUpperHullIndexes(points) { - var n = points.length, - indexes = [0, 1], - size = 2; +function bindKey(parent, group, enter, update, exit, data, key) { + var i, + node, + nodeByKeyValue = {}, + groupLength = group.length, + dataLength = data.length, + keyValues = new Array(groupLength), + keyValue; - for (var i = 2; i < n; ++i) { - while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; - indexes[size++] = i; + // Compute the key for each node. + // If multiple nodes have the same key, the duplicates are added to exit. + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); + if (keyValue in nodeByKeyValue) { + exit[i] = node; + } else { + nodeByKeyValue[keyValue] = node; + } + } } - return indexes.slice(0, size); // remove popped points + // Compute the key for each datum. + // If there a node associated with this key, join and add it to update. + // If there is not (or the key is a duplicate), add it to enter. + for (i = 0; i < dataLength; ++i) { + keyValue = keyPrefix + key.call(parent, data[i], i, data); + if (node = nodeByKeyValue[keyValue]) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue[keyValue] = null; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Add any remaining nodes that were not bound to data to exit. + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { + exit[i] = node; + } + } } -var hull = function(points) { - if ((n = points.length) < 3) return null; +var selection_data = function(value, key) { + if (!value) { + data = new Array(this.size()), j = -1; + this.each(function(d) { data[++j] = d; }); + return data; + } - var i, - n, - sortedPoints = new Array(n), - flippedPoints = new Array(n); + var bind = key ? bindKey : bindIndex, + parents = this._parents, + groups = this._groups; - for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i]; - sortedPoints.sort(lexicographicOrder); - for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; + if (typeof value !== "function") value = constant$1(value); - var upperIndexes = computeUpperHullIndexes(sortedPoints), - lowerIndexes = computeUpperHullIndexes(flippedPoints); + for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { + var parent = parents[j], + group = groups[j], + groupLength = group.length, + data = value.call(parent, parent && parent.__data__, j, parents), + dataLength = data.length, + enterGroup = enter[j] = new Array(dataLength), + updateGroup = update[j] = new Array(dataLength), + exitGroup = exit[j] = new Array(groupLength); - // Construct the hull polygon, removing possible duplicate endpoints. - var skipLeft = lowerIndexes[0] === upperIndexes[0], - skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], - hull = []; + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); - // Add upper hull in right-to-l order. - // Then add lower hull in left-to-right order. - for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]); - for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); + // Now connect the enter nodes to their following update node, such that + // appendChild can insert the materialized enter node before this node, + // rather than at the end of the parent node. + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength); + previous._next = next || null; + } + } + } - return hull; + update = new Selection(update, parents); + update._enter = enter; + update._exit = exit; + return update; }; -var contains = function(polygon, point) { - var n = polygon.length, - p = polygon[n - 1], - x = point[0], y = point[1], - x0 = p[0], y0 = p[1], - x1, y1, - inside = false; +var selection_exit = function() { + return new Selection(this._exit || this._groups.map(sparse), this._parents); +}; - for (var i = 0; i < n; ++i) { - p = polygon[i], x1 = p[0], y1 = p[1]; - if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside; - x0 = x1, y0 = y1; +var selection_merge = function(selection) { + + for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } } - return inside; + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Selection(merges, this._parents); }; -var length$1 = function(polygon) { - var i = -1, - n = polygon.length, - b = polygon[n - 1], - xa, - ya, - xb = b[0], - yb = b[1], - perimeter = 0; +var selection_order = function() { - while (++i < n) { - xa = xb; - ya = yb; - b = polygon[i]; - xb = b[0]; - yb = b[1]; - xa -= xb; - ya -= yb; - perimeter += Math.sqrt(xa * xa + ya * ya); + for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { + for (var group = groups[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 perimeter; + return this; }; -var pi$1 = Math.PI; -var tau$1 = 2 * pi$1; -var epsilon = 1e-6; -var tauEpsilon = tau$1 - epsilon; - -function Path() { - this._x0 = this._y0 = // start of current subpath - this._x1 = this._y1 = null; // end of current subpath - this._ = []; -} +var selection_sort = function(compare) { + if (!compare) compare = ascending$1; -function path() { - return new Path; -} + function compareNode(a, b) { + return a && b ? compare(a.__data__, b.__data__) : !a - !b; + } -Path.prototype = path.prototype = { - constructor: Path, - moveTo: function(x, y) { - this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y); - }, - closePath: function() { - if (this._x1 !== null) { - this._x1 = this._x0, this._y1 = this._y0; - this._.push("Z"); + for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } } - }, - lineTo: function(x, y) { - this._.push("L", this._x1 = +x, ",", this._y1 = +y); - }, - quadraticCurveTo: function(x1, y1, x, y) { - this._.push("Q", +x1, ",", +y1, ",", this._x1 = +x, ",", this._y1 = +y); - }, - bezierCurveTo: function(x1, y1, x2, y2, x, y) { - this._.push("C", +x1, ",", +y1, ",", +x2, ",", +y2, ",", this._x1 = +x, ",", this._y1 = +y); - }, - arcTo: function(x1, y1, x2, y2, r) { - x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; - var x0 = this._x1, - y0 = this._y1, - x21 = x2 - x1, - y21 = y2 - y1, - x01 = x0 - x1, - y01 = y0 - y1, - l01_2 = x01 * x01 + y01 * y01; - - // Is the radius negative? Error. - if (r < 0) throw new Error("negative radius: " + r); + sortgroup.sort(compareNode); + } - // Is this path empty? Move to (x1,y1). - if (this._x1 === null) { - this._.push( - "M", this._x1 = x1, ",", this._y1 = y1 - ); - } + return new Selection(sortgroups, this._parents).order(); +}; - // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. - else if (!(l01_2 > epsilon)) {} +function ascending$1(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +} - // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? - // Equivalently, is (x1,y1) coincident with (x2,y2)? - // Or, is the radius zero? Line to (x1,y1). - else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) { - this._.push( - "L", this._x1 = x1, ",", this._y1 = y1 - ); - } +var selection_call = function() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; +}; - // Otherwise, draw an arc! - else { - var x20 = x2 - x0, - y20 = y2 - y0, - l21_2 = x21 * x21 + y21 * y21, - l20_2 = x20 * x20 + y20 * y20, - l21 = Math.sqrt(l21_2), - l01 = Math.sqrt(l01_2), - l = r * Math.tan((pi$1 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), - t01 = l / l01, - t21 = l / l21; +var selection_nodes = function() { + var nodes = new Array(this.size()), i = -1; + this.each(function() { nodes[++i] = this; }); + return nodes; +}; - // If the start tangent is not coincident with (x0,y0), line to. - if (Math.abs(t01 - 1) > epsilon) { - this._.push( - "L", x1 + t01 * x01, ",", y1 + t01 * y01 - ); - } +var selection_node = function() { - this._.push( - "A", r, ",", r, ",0,0,", +(y01 * x20 > x01 * y20), ",", this._x1 = x1 + t21 * x21, ",", this._y1 = y1 + t21 * y21 - ); + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) return node; } - }, - arc: function(x, y, r, a0, a1, ccw) { - x = +x, y = +y, r = +r; - var dx = r * Math.cos(a0), - dy = r * Math.sin(a0), - x0 = x + dx, - y0 = y + dy, - cw = 1 ^ ccw, - da = ccw ? a0 - a1 : a1 - a0; - - // Is the radius negative? Error. - if (r < 0) throw new Error("negative radius: " + r); + } - // Is this path empty? Move to (x0,y0). - if (this._x1 === null) { - this._.push( - "M", x0, ",", y0 - ); - } + return null; +}; - // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). - else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) { - this._.push( - "L", x0, ",", y0 - ); - } +var selection_size = function() { + var size = 0; + this.each(function() { ++size; }); + return size; +}; - // Is this arc empty? We’re done. - if (!r) return; +var selection_empty = function() { + return !this.node(); +}; - // Is this a complete circle? Draw two arcs to complete the circle. - if (da > tauEpsilon) { - this._.push( - "A", r, ",", r, ",0,1,", cw, ",", x - dx, ",", y - dy, - "A", r, ",", r, ",0,1,", cw, ",", this._x1 = x0, ",", this._y1 = y0 - ); - } +var selection_each = function(callback) { - // Otherwise, draw an arc! - else { - if (da < 0) da = da % tau$1 + tau$1; - this._.push( - "A", r, ",", r, ",0,", +(da >= pi$1), ",", cw, ",", this._x1 = x + r * Math.cos(a1), ",", this._y1 = y + r * Math.sin(a1) - ); + for (var groups = this._groups, 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.call(node, node.__data__, i, group); } - }, - rect: function(x, y, w, h) { - this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y, "h", +w, "v", +h, "h", -w, "Z"); - }, - toString: function() { - return this._.join(""); } -}; -var tree_add = function(d) { - var x = +this._x.call(null, d), - y = +this._y.call(null, d); - return add(this.cover(x, y), x, y, d); + return this; }; -function add(tree, x, y, d) { - if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points +function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; +} - var parent, - node = tree._root, - leaf = {data: d}, - x0 = tree._x0, - y0 = tree._y0, - x1 = tree._x1, - y1 = tree._y1, - xm, - ym, - xp, - yp, - right, - bottom, - i, - j; +function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; +} - // If the tree is empty, initialize the root as a leaf. - if (!node) return tree._root = leaf, tree; +function attrConstant(name, value) { + return function() { + this.setAttribute(name, value); + }; +} - // Find the existing leaf for the new point, or add it. - while (node.length) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; - } +function attrConstantNS(fullname, value) { + return function() { + this.setAttributeNS(fullname.space, fullname.local, value); + }; +} - // Is the new point is exactly coincident with the existing point? - xp = +tree._x.call(null, node.data); - yp = +tree._y.call(null, node.data); - if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; +function attrFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttribute(name); + else this.setAttribute(name, v); + }; +} - // Otherwise, split the leaf node until the old and new point are separated. - do { - parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); - return parent[j] = node, parent[i] = leaf, tree; +function attrFunctionNS(fullname, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttributeNS(fullname.space, fullname.local); + else this.setAttributeNS(fullname.space, fullname.local, v); + }; } -function addAll(data) { - var d, i, n = data.length, - x, - y, - xz = new Array(n), - yz = new Array(n), - x0 = Infinity, - y0 = Infinity, - x1 = -Infinity, - y1 = -Infinity; +var selection_attr = function(name, value) { + var fullname = namespace(name); - // Compute the points and their extent. - for (i = 0; i < n; ++i) { - if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; - xz[i] = x; - yz[i] = y; - if (x < x0) x0 = x; - if (x > x1) x1 = x; - if (y < y0) y0 = y; - if (y > y1) y1 = y; + if (arguments.length < 2) { + var node = this.node(); + return fullname.local + ? node.getAttributeNS(fullname.space, fullname.local) + : node.getAttribute(fullname); } - // If there were no (valid) points, inherit the existing extent. - if (x1 < x0) x0 = this._x0, x1 = this._x1; - if (y1 < y0) y0 = this._y0, y1 = this._y1; - - // Expand the tree to cover the new points. - this.cover(x0, y0).cover(x1, y1); + return this.each((value == null + ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" + ? (fullname.local ? attrFunctionNS : attrFunction) + : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); +}; - // Add the new points. - for (i = 0; i < n; ++i) { - add(this, xz[i], yz[i], data[i]); - } +var window = function(node) { + return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node + || (node.document && node) // node is a Window + || node.defaultView; // node is a Document +}; - return this; +function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; } -var tree_cover = function(x, y) { - if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points - - var x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1; +function styleConstant(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; +} - // If the quadtree has no extent, initialize them. - // Integer extent are necessary so that if we later double the extent, - // the existing quadrant boundaries don’t change due to floating point error! - if (isNaN(x0)) { - x1 = (x0 = Math.floor(x)) + 1; - y1 = (y0 = Math.floor(y)) + 1; - } - - // Otherwise, double repeatedly to cover. - else if (x0 > x || x > x1 || y0 > y || y > y1) { - var z = x1 - x0, - node = this._root, - parent, - i; +function styleFunction(name, value, priority) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.style.removeProperty(name); + else this.style.setProperty(name, v, priority); + }; +} - switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { - case 0: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); - break; - } - case 1: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); - break; - } - case 2: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); - break; - } - case 3: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); - break; - } - } +var selection_style = function(name, value, priority) { + var node; + return arguments.length > 1 + ? this.each((value == null + ? styleRemove : typeof value === "function" + ? styleFunction + : styleConstant)(name, value, priority == null ? "" : priority)) + : window(node = this.node()) + .getComputedStyle(node, null) + .getPropertyValue(name); +}; - if (this._root && this._root.length) this._root = node; - } +function propertyRemove(name) { + return function() { + delete this[name]; + }; +} - // If the quadtree covers the point already, just return. - else return this; +function propertyConstant(name, value) { + return function() { + this[name] = value; + }; +} - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - return this; -}; +function propertyFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) delete this[name]; + else this[name] = v; + }; +} -var tree_data = function() { - var data = []; - this.visit(function(node) { - if (!node.length) do data.push(node.data); while (node = node.next) - }); - return data; +var selection_property = function(name, value) { + return arguments.length > 1 + ? this.each((value == null + ? propertyRemove : typeof value === "function" + ? propertyFunction + : propertyConstant)(name, value)) + : this.node()[name]; }; -var tree_extent = function(_) { - return arguments.length - ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) - : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; -}; +function classArray(string) { + return string.trim().split(/^|\s+/); +} -var Quad = function(node, x0, y0, x1, y1) { - this.node = node; - this.x0 = x0; - this.y0 = y0; - this.x1 = x1; - this.y1 = y1; -}; +function classList(node) { + return node.classList || new ClassList(node); +} -var tree_find = function(x, y, radius) { - var data, - x0 = this._x0, - y0 = this._y0, - x1, - y1, - x2, - y2, - x3 = this._x1, - y3 = this._y1, - quads = [], - node = this._root, - q, - i; +function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); +} - if (node) quads.push(new Quad(node, x0, y0, x3, y3)); - if (radius == null) radius = Infinity; - else { - x0 = x - radius, y0 = y - radius; - x3 = x + radius, y3 = y + radius; - radius *= radius; +ClassList.prototype = { + add: function(name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function(name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function(name) { + return this._names.indexOf(name) >= 0; } +}; - while (q = quads.pop()) { +function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.add(names[i]); +} - // Stop searching if this quadrant can’t contain a closer node. - if (!(node = q.node) - || (x1 = q.x0) > x3 - || (y1 = q.y0) > y3 - || (x2 = q.x1) < x0 - || (y2 = q.y1) < y0) continue; +function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.remove(names[i]); +} - // Bisect the current quadrant. - if (node.length) { - var xm = (x1 + x2) / 2, - ym = (y1 + y2) / 2; +function classedTrue(names) { + return function() { + classedAdd(this, names); + }; +} - quads.push( - new Quad(node[3], xm, ym, x2, y2), - new Quad(node[2], x1, ym, xm, y2), - new Quad(node[1], xm, y1, x2, ym), - new Quad(node[0], x1, y1, xm, ym) - ); +function classedFalse(names) { + return function() { + classedRemove(this, names); + }; +} - // Visit the closest quadrant first. - if (i = (y >= ym) << 1 | (x >= xm)) { - q = quads[quads.length - 1]; - quads[quads.length - 1] = quads[quads.length - 1 - i]; - quads[quads.length - 1 - i] = q; - } - } +function classedFunction(names, value) { + return function() { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; +} - // Visit this point. (Visiting coincident points isn’t necessary!) - else { - var dx = x - +this._x.call(null, node.data), - dy = y - +this._y.call(null, node.data), - d2 = dx * dx + dy * dy; - if (d2 < radius) { - var d = Math.sqrt(radius = d2); - x0 = x - d, y0 = y - d; - x3 = x + d, y3 = y + d; - data = node.data; - } - } +var selection_classed = function(name, value) { + var names = classArray(name + ""); + + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) if (!list.contains(names[i])) return false; + return true; } - return data; + return this.each((typeof value === "function" + ? classedFunction : value + ? classedTrue + : classedFalse)(names, value)); }; -var tree_remove = function(d) { - if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points - - var parent, - node = this._root, - retainer, - previous, - next, - x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1, - x, - y, - xm, - ym, - right, - bottom, - i, - j; +function textRemove() { + this.textContent = ""; +} - // If the tree is empty, initialize the root as a leaf. - if (!node) return this; +function textConstant(value) { + return function() { + this.textContent = value; + }; +} - // Find the leaf node for the point. - // While descending, also retain the deepest parent with a non-removed sibling. - if (node.length) while (true) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (!(parent = node, node = node[i = bottom << 1 | right])) return this; - if (!node.length) break; - if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; - } +function textFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + }; +} - // Find the point to remove. - while (node.data !== d) if (!(previous = node, node = node.next)) return this; - if (next = node.next) delete node.next; +var selection_text = function(value) { + return arguments.length + ? this.each(value == null + ? textRemove : (typeof value === "function" + ? textFunction + : textConstant)(value)) + : this.node().textContent; +}; - // If there are multiple coincident points, remove just the point. - if (previous) return (next ? previous.next = next : delete previous.next), this; +function htmlRemove() { + this.innerHTML = ""; +} - // If this is the root point, remove it. - if (!parent) return this._root = next, this; +function htmlConstant(value) { + return function() { + this.innerHTML = value; + }; +} - // Remove this leaf. - next ? parent[i] = next : delete parent[i]; +function htmlFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + }; +} - // If the parent now contains exactly one leaf, collapse superfluous parents. - if ((node = parent[0] || parent[1] || parent[2] || parent[3]) - && node === (parent[3] || parent[2] || parent[1] || parent[0]) - && !node.length) { - if (retainer) retainer[j] = node; - else this._root = node; - } +var selection_html = function(value) { + return arguments.length + ? this.each(value == null + ? htmlRemove : (typeof value === "function" + ? htmlFunction + : htmlConstant)(value)) + : this.node().innerHTML; +}; - return this; +function raise() { + if (this.nextSibling) this.parentNode.appendChild(this); +} + +var selection_raise = function() { + return this.each(raise); }; -function removeAll(data) { - for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); - return this; +function lower() { + if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); } -var tree_root = function() { - return this._root; +var selection_lower = function() { + return this.each(lower); }; -var tree_size = function() { - var size = 0; - this.visit(function(node) { - if (!node.length) do ++size; while (node = node.next) +var selection_append = function(name) { + var create = typeof name === "function" ? name : creator(name); + return this.select(function() { + return this.appendChild(create.apply(this, arguments)); }); - return size; }; -var tree_visit = function(callback) { - var quads = [], q, node = this._root, child, x0, y0, x1, y1; - if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { - var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - } - } - return this; -}; +function constantNull() { + return null; +} -var tree_visitAfter = function(callback) { - var quads = [], next = [], q; - if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - var node = q.node; - if (node.length) { - var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - } - next.push(q); - } - while (q = next.pop()) { - callback(q.node, q.x0, q.y0, q.x1, q.y1); - } - return this; +var selection_insert = function(name, before) { + var create = typeof name === "function" ? name : creator(name), + select = before == null ? constantNull : typeof before === "function" ? before : selector(before); + return this.select(function() { + return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); + }); }; -function defaultX(d) { - return d[0]; +function remove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); } -var tree_x = function(_) { - return arguments.length ? (this._x = _, this) : this._x; +var selection_remove = function() { + return this.each(remove); }; -function defaultY(d) { - return d[1]; +var selection_datum = function(value) { + return arguments.length + ? this.property("__data__", value) + : this.node().__data__; +}; + +function dispatchEvent(node, type, params) { + var window$$1 = window(node), + event = window$$1.CustomEvent; + + if (event) { + event = new event(type, params); + } else { + event = window$$1.document.createEvent("Event"); + if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; + else event.initEvent(type, false, false); + } + + node.dispatchEvent(event); } -var tree_y = function(_) { - return arguments.length ? (this._y = _, this) : this._y; -}; +function dispatchConstant(type, params) { + return function() { + return dispatchEvent(this, type, params); + }; +} -function quadtree(nodes, x, y) { - var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); - return nodes == null ? tree : tree.addAll(nodes); +function dispatchFunction(type, params) { + return function() { + return dispatchEvent(this, type, params.apply(this, arguments)); + }; } -function Quadtree(x, y, x0, y0, x1, y1) { - this._x = x; - this._y = y; - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - this._root = undefined; +var selection_dispatch = function(type, params) { + return this.each((typeof params === "function" + ? dispatchFunction + : dispatchConstant)(type, params)); +}; + +var root = [null]; + +function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; } -function leaf_copy(leaf) { - var copy = {data: leaf.data}, next = copy; - while (leaf = leaf.next) next = next.next = {data: leaf.data}; - return copy; +function selection() { + return new Selection([[document.documentElement]], root); } -var treeProto = quadtree.prototype = Quadtree.prototype; +Selection.prototype = selection.prototype = { + constructor: Selection, + select: selection_select, + selectAll: selection_selectAll, + filter: selection_filter, + data: selection_data, + enter: selection_enter, + exit: selection_exit, + merge: selection_merge, + order: selection_order, + sort: selection_sort, + call: selection_call, + nodes: selection_nodes, + node: selection_node, + size: selection_size, + empty: selection_empty, + each: selection_each, + attr: selection_attr, + style: selection_style, + property: selection_property, + classed: selection_classed, + text: selection_text, + html: selection_html, + raise: selection_raise, + lower: selection_lower, + append: selection_append, + insert: selection_insert, + remove: selection_remove, + datum: selection_datum, + on: selection_on, + dispatch: selection_dispatch +}; -treeProto.copy = function() { - var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), - node = this._root, - nodes, - child; +var select = function(selector) { + return typeof selector === "string" + ? new Selection([[document.querySelector(selector)]], [document.documentElement]) + : new Selection([[selector]], root); +}; - if (!node) return copy; +var selectAll = function(selector) { + return typeof selector === "string" + ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) + : new Selection([selector == null ? [] : selector], root); +}; - if (!node.length) return copy._root = leaf_copy(node), copy; +var touch = function(node, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; - nodes = [{source: node, target: copy._root = new Array(4)}]; - while (node = nodes.pop()) { - for (var i = 0; i < 4; ++i) { - if (child = node.source[i]) { - if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); - else node.target[i] = leaf_copy(child); - } + for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return point(node, touch); } } - return copy; + return null; }; -treeProto.add = tree_add; -treeProto.addAll = addAll; -treeProto.cover = tree_cover; -treeProto.data = tree_data; -treeProto.extent = tree_extent; -treeProto.find = tree_find; -treeProto.remove = tree_remove; -treeProto.removeAll = removeAll; -treeProto.root = tree_root; -treeProto.size = tree_size; -treeProto.visit = tree_visit; -treeProto.visitAfter = tree_visitAfter; -treeProto.x = tree_x; -treeProto.y = tree_y; +var touches = function(node, touches) { + if (touches == null) touches = sourceEvent().touches; -var slice$1 = [].slice; + for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { + points[i] = point(node, touches[i]); + } -var noabort = {}; + return points; +}; -function Queue(size) { - if (!(size >= 1)) throw new Error; - this._size = size; - this._call = - this._error = null; - this._tasks = []; - this._data = []; - this._waiting = - this._active = - this._ended = - this._start = 0; // inside a synchronous task callback? +function nopropagation() { + exports.event.stopImmediatePropagation(); } -Queue.prototype = queue.prototype = { - constructor: Queue, - defer: function(callback) { - if (typeof callback !== "function" || this._call) throw new Error; - if (this._error != null) return this; - var t = slice$1.call(arguments, 1); - t.push(callback); - ++this._waiting, this._tasks.push(t); - poke(this); - return this; - }, - abort: function() { - if (this._error == null) abort(this, new Error("abort")); - return this; - }, - await: function(callback) { - if (typeof callback !== "function" || this._call) throw new Error; - this._call = function(error, results) { callback.apply(null, [error].concat(results)); }; - maybeNotify(this); - return this; - }, - awaitAll: function(callback) { - if (typeof callback !== "function" || this._call) throw new Error; - this._call = callback; - maybeNotify(this); - return this; - } +var noevent = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); }; -function poke(q) { - if (!q._start) { - try { start(q); } // let the current task complete - catch (e) { - if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously - else if (!q._data) throw e; // await callback errored synchronously - } - } -} - -function start(q) { - while (q._start = q._waiting && q._active < q._size) { - var i = q._ended + q._active, - t = q._tasks[i], - j = t.length - 1, - c = t[j]; - t[j] = end(q, i); - --q._waiting, ++q._active; - t = c.apply(null, t); - if (!q._tasks[i]) continue; // task finished synchronously - q._tasks[i] = t || noabort; +var dragDisable = function(view) { + var root = view.document.documentElement, + selection$$1 = select(view).on("dragstart.drag", noevent, true); + if ("onselectstart" in root) { + selection$$1.on("selectstart.drag", noevent, true); + } else { + root.__noselect = root.style.MozUserSelect; + root.style.MozUserSelect = "none"; } -} - -function end(q, i) { - return function(e, r) { - if (!q._tasks[i]) return; // ignore multiple callbacks - --q._active, ++q._ended; - q._tasks[i] = null; - if (q._error != null) return; // ignore secondary errors - if (e != null) { - abort(q, e); - } else { - q._data[i] = r; - if (q._waiting) poke(q); - else maybeNotify(q); - } - }; -} - -function abort(q, e) { - var i = q._tasks.length, t; - q._error = e; // ignore active callbacks - q._data = undefined; // allow gc - q._waiting = NaN; // prevent starting +}; - while (--i >= 0) { - if (t = q._tasks[i]) { - q._tasks[i] = null; - if (t.abort) { - try { t.abort(); } - catch (e) { /* ignore */ } - } - } +function yesdrag(view, noclick) { + var root = view.document.documentElement, + selection$$1 = select(view).on("dragstart.drag", null); + if (noclick) { + selection$$1.on("click.drag", noevent, true); + setTimeout(function() { selection$$1.on("click.drag", null); }, 0); } - - q._active = NaN; // allow notification - maybeNotify(q); -} - -function maybeNotify(q) { - if (!q._active && q._call) { - var d = q._data; - q._data = undefined; // allow gc - q._call(q._error, d); + if ("onselectstart" in root) { + selection$$1.on("selectstart.drag", null); + } else { + root.style.MozUserSelect = root.__noselect; + delete root.__noselect; } } -function queue(concurrency) { - return new Queue(arguments.length ? +concurrency : Infinity); -} - var constant$2 = function(x) { - return function constant() { + return function() { return x; }; }; -var epsilon$1 = 1e-12; -var pi$2 = Math.PI; -var halfPi$1 = pi$2 / 2; -var tau$2 = 2 * pi$2; - -function arcInnerRadius(d) { - return d.innerRadius; +function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) { + this.target = target; + this.type = type; + this.subject = subject; + this.identifier = id; + this.active = active; + this.x = x; + this.y = y; + this.dx = dx; + this.dy = dy; + this._ = dispatch; } -function arcOuterRadius(d) { - return d.outerRadius; -} +DragEvent.prototype.on = function() { + var value = this._.on.apply(this._, arguments); + return value === this._ ? this : value; +}; -function arcStartAngle(d) { - return d.startAngle; +// Ignore right-click, since that should open the context menu. +function defaultFilter$1() { + return !exports.event.button; } -function arcEndAngle(d) { - return d.endAngle; +function defaultContainer() { + return this.parentNode; } -function arcPadAngle(d) { - return d && d.padAngle; // Note: optional! +function defaultSubject(d) { + return d == null ? {x: exports.event.x, y: exports.event.y} : d; } -function asin(x) { - return x >= 1 ? halfPi$1 : x <= -1 ? -halfPi$1 : Math.asin(x); -} +var drag = function() { + var filter = defaultFilter$1, + container = defaultContainer, + subject = defaultSubject, + gestures = {}, + listeners = dispatch("start", "drag", "end"), + active = 0, + mousemoving, + touchending; -function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { - var x10 = x1 - x0, y10 = y1 - y0, - x32 = x3 - x2, y32 = y3 - y2, - t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); - return [x0 + t * x10, y0 + t * y10]; -} + function drag(selection$$1) { + selection$$1 + .on("mousedown.drag", mousedowned) + .on("touchstart.drag", touchstarted) + .on("touchmove.drag", touchmoved) + .on("touchend.drag touchcancel.drag", touchended) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } -// Compute perpendicular offset line of length rc. -// http://mathworld.wolfram.com/Circle-LineIntersection.html -function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { - var x01 = x0 - x1, - y01 = y0 - y1, - lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), - ox = lo * y01, - oy = -lo * x01, - x11 = x0 + ox, - y11 = y0 + oy, - x10 = x1 + ox, - y10 = y1 + oy, - x00 = (x11 + x10) / 2, - y00 = (y11 + y10) / 2, - dx = x10 - x11, - dy = y10 - y11, - d2 = dx * dx + dy * dy, - r = r1 - rc, - D = x11 * y10 - x10 * y11, - 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 - x00, - dy0 = cy0 - y00, - dx1 = cx1 - x00, - dy1 = cy1 - y00; + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments); + if (!gesture) return; + select(exports.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); + dragDisable(exports.event.view); + nopropagation(); + mousemoving = false; + gesture("start"); + } - // Pick the closer of the two intersection points. - // TODO Is there a faster way to determine which intersection to use? - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + function mousemoved() { + noevent(); + mousemoving = true; + gestures.mouse("drag"); + } - return { - cx: cx0, - cy: cy0, - x01: -ox, - y01: -oy, - x11: cx0 * (r1 / r - 1), - y11: cy0 * (r1 / r - 1) - }; -} - -var arc = function() { - var innerRadius = arcInnerRadius, - outerRadius = arcOuterRadius, - cornerRadius = constant$2(0), - padRadius = null, - startAngle = arcStartAngle, - endAngle = arcEndAngle, - padAngle = arcPadAngle, - context = null; - - function arc() { - var buffer, - r, - r0 = +innerRadius.apply(this, arguments), - r1 = +outerRadius.apply(this, arguments), - a0 = startAngle.apply(this, arguments) - halfPi$1, - a1 = endAngle.apply(this, arguments) - halfPi$1, - da = Math.abs(a1 - a0), - cw = a1 > a0; - - if (!context) context = buffer = path(); - - // Ensure that the outer radius is always larger than the inner radius. - if (r1 < r0) r = r1, r1 = r0, r0 = r; + function mouseupped() { + select(exports.event.view).on("mousemove.drag mouseup.drag", null); + yesdrag(exports.event.view, mousemoving); + noevent(); + gestures.mouse("end"); + } - // Is it a point? - if (!(r1 > epsilon$1)) context.moveTo(0, 0); + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var touches$$1 = exports.event.changedTouches, + c = container.apply(this, arguments), + n = touches$$1.length, i, gesture; - // Or is it a circle or annulus? - else if (da > tau$2 - epsilon$1) { - context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0)); - context.arc(0, 0, r1, a0, a1, !cw); - if (r0 > epsilon$1) { - context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1)); - context.arc(0, 0, r0, a1, a0, cw); + for (i = 0; i < n; ++i) { + if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) { + nopropagation(); + gesture("start"); } } + } - // Or is it a circular or annular sector? - else { - var a01 = a0, - a11 = a1, - a00 = a0, - a10 = a1, - da0 = da, - da1 = da, - ap = padAngle.apply(this, arguments) / 2, - rp = (ap > epsilon$1) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)), - rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), - rc0 = rc, - rc1 = rc, - t0, - t1; - - // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. - if (rp > epsilon$1) { - var p0 = asin(rp / r0 * Math.sin(ap)), - p1 = asin(rp / r1 * Math.sin(ap)); - if ((da0 -= p0 * 2) > epsilon$1) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; - else da0 = 0, a00 = a10 = (a0 + a1) / 2; - if ((da1 -= p1 * 2) > epsilon$1) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; - else da1 = 0, a01 = a11 = (a0 + a1) / 2; - } - - var x01 = r1 * Math.cos(a01), - y01 = r1 * Math.sin(a01), - x10 = r0 * Math.cos(a10), - y10 = r0 * Math.sin(a10); - - // Apply rounded corners? - if (rc > epsilon$1) { - var x11 = r1 * Math.cos(a11), - y11 = r1 * Math.sin(a11), - x00 = r0 * Math.cos(a00), - y00 = r0 * Math.sin(a00); - - // Restrict the corner radius according to the sector angle. - if (da < pi$2) { - var oc = da0 > epsilon$1 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], - ax = x01 - oc[0], - ay = y01 - oc[1], - bx = x11 - oc[0], - by = y11 - 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)); - } - } - - // Is the sector collapsed to a line? - if (!(da1 > epsilon$1)) context.moveTo(x01, y01); - - // Does the sector’s outer ring have rounded corners? - else if (rc1 > epsilon$1) { - t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); - t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); - - context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); - - // Have the corners merged? - if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); + function touchmoved() { + var touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, gesture; - // Otherwise, draw the two corners and the ring. - else { - context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); - context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); - context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); - } + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches$$1[i].identifier]) { + noevent(); + gesture("drag"); } + } + } - // Or is the outer ring just a circular arc? - else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); - - // Is there no inner ring, and it’s a circular sector? - // Or perhaps it’s an annular sector collapsed due to padding? - if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10); - - // Does the sector’s inner ring (or point) have rounded corners? - else if (rc0 > epsilon$1) { - t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); - t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); - - context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); - - // Have the corners merged? - if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); + function touchended() { + var touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, gesture; - // Otherwise, draw the two corners and the ring. - else { - context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); - context.arc(0, 0, r0, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); - context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); - } + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches$$1[i].identifier]) { + nopropagation(); + gesture("end"); } - - // Or is the inner ring just a circular arc? - else context.arc(0, 0, r0, a10, a00, cw); } - - context.closePath(); - - if (buffer) return context = null, buffer + "" || null; } - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, - a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$2 / 2; - return [Math.cos(a) * r, Math.sin(a) * r]; - }; - - arc.innerRadius = function(_) { - return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : innerRadius; - }; - - arc.outerRadius = function(_) { - return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : outerRadius; - }; + function beforestart(id, container, point, that, args) { + var p = point(container, id), s, dx, dy, + sublisteners = listeners.copy(); - arc.cornerRadius = function(_) { - return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : cornerRadius; - }; + if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { + if ((exports.event.subject = s = subject.apply(that, args)) == null) return false; + dx = s.x - p[0] || 0; + dy = s.y - p[1] || 0; + return true; + })) return; - arc.padRadius = function(_) { - return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), arc) : padRadius; - }; + return function gesture(type) { + var p0 = p, n; + switch (type) { + case "start": gestures[id] = gesture, n = active++; break; + case "end": delete gestures[id], --active; // nobreak + case "drag": p = point(container, id), n = active; break; + } + customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); + }; + } - arc.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : startAngle; + drag.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter; }; - arc.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : endAngle; + drag.container = function(_) { + return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container; }; - arc.padAngle = function(_) { - return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : padAngle; + drag.subject = function(_) { + return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject; }; - arc.context = function(_) { - return arguments.length ? ((context = _ == null ? null : _), arc) : context; + drag.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? drag : value; }; - return arc; -}; - -function Linear(context) { - this._context = context; -} - -Linear.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; // proceed - default: this._context.lineTo(x, y); break; - } - } + return drag; }; -var curveLinear = function(context) { - return new Linear(context); +var define = function(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; }; -function x(p) { - return p[0]; +function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) prototype[key] = definition[key]; + return prototype; } -function y(p) { - return p[1]; -} +function Color() {} -var line = function() { - var x$$1 = x, - y$$1 = y, - defined = constant$2(true), - context = null, - curve = curveLinear, - output = null; +var darker = 0.7; +var brighter = 1 / darker; - function line(data) { - var i, - n = data.length, - d, - defined0 = false, - buffer; +var reI = "\\s*([+-]?\\d+)\\s*"; +var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*"; +var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; +var reHex3 = /^#([0-9a-f]{3})$/; +var reHex6 = /^#([0-9a-f]{6})$/; +var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"); +var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"); +var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"); +var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"); +var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"); +var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); - if (context == null) output = curve(buffer = path()); - - for (i = 0; i <= n; ++i) { - if (!(i < n && defined(d = data[i], i, data)) === defined0) { - if (defined0 = !defined0) output.lineStart(); - else output.lineEnd(); - } - if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); - } - - if (buffer) return output = null, buffer + "" || null; - } - - line.x = function(_) { - return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : x$$1; - }; - - line.y = function(_) { - return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : y$$1; - }; - - line.defined = function(_) { - return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), line) : defined; - }; - - line.curve = function(_) { - return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; - }; - - line.context = function(_) { - return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; - }; - - return line; -}; - -var area$1 = function() { - var x0 = x, - x1 = null, - y0 = constant$2(0), - y1 = y, - defined = constant$2(true), - context = null, - curve = curveLinear, - output = null; - - function area(data) { - var i, - j, - k, - n = data.length, - d, - defined0 = false, - buffer, - x0z = new Array(n), - y0z = new Array(n); - - if (context == null) output = curve(buffer = path()); - - for (i = 0; i <= n; ++i) { - if (!(i < n && defined(d = data[i], i, data)) === defined0) { - if (defined0 = !defined0) { - j = i; - output.areaStart(); - output.lineStart(); - } else { - output.lineEnd(); - output.lineStart(); - for (k = i - 1; k >= j; --k) { - output.point(x0z[k], y0z[k]); - } - output.lineEnd(); - output.areaEnd(); - } - } - if (defined0) { - x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); - output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); - } - } - - if (buffer) return output = null, buffer + "" || null; - } - - function arealine() { - return line().defined(defined).curve(curve).context(context); - } - - area.x = function(_) { - return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), x1 = null, area) : x0; - }; - - area.x0 = function(_) { - return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), area) : x0; - }; - - area.x1 = function(_) { - return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : x1; - }; - - area.y = function(_) { - return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), y1 = null, area) : y0; - }; - - area.y0 = function(_) { - return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), area) : y0; - }; - - area.y1 = function(_) { - return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : y1; - }; - - area.lineX0 = - area.lineY0 = function() { - return arealine().x(x0).y(y0); - }; - - area.lineY1 = function() { - return arealine().x(x0).y(y1); - }; - - area.lineX1 = function() { - return arealine().x(x1).y(y0); - }; - - area.defined = function(_) { - return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), area) : defined; - }; - - area.curve = function(_) { - return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; - }; - - area.context = function(_) { - return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; - }; - - return area; -}; - -var descending$1 = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; -}; - -var identity$1 = function(d) { - return d; -}; - -var pie = function() { - var value = identity$1, - sortValues = descending$1, - sort = null, - startAngle = constant$2(0), - endAngle = constant$2(tau$2), - padAngle = constant$2(0); - - function pie(data) { - var i, - n = data.length, - j, - k, - sum = 0, - index = new Array(n), - arcs = new Array(n), - a0 = +startAngle.apply(this, arguments), - da = Math.min(tau$2, Math.max(-tau$2, endAngle.apply(this, arguments) - a0)), - a1, - p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), - pa = p * (da < 0 ? -1 : 1), - v; - - for (i = 0; i < n; ++i) { - if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { - sum += v; - } - } - - // Optionally sort the arcs by previously-computed values or by data. - if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); - else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); - - // Compute the arcs! They are stored in the original data's order. - for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { - j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { - data: data[j], - index: i, - value: v, - startAngle: a0, - endAngle: a1, - padAngle: p - }; - } - - return arcs; - } - - pie.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), pie) : value; - }; - - pie.sortValues = function(_) { - return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; - }; - - pie.sort = function(_) { - return arguments.length ? (sort = _, sortValues = null, pie) : sort; - }; - - pie.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : startAngle; - }; - - pie.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : endAngle; - }; - - pie.padAngle = function(_) { - return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : padAngle; - }; - - return pie; -}; - -var curveRadialLinear = curveRadial(curveLinear); - -function Radial(curve) { - this._curve = curve; -} - -Radial.prototype = { - areaStart: function() { - this._curve.areaStart(); - }, - areaEnd: function() { - this._curve.areaEnd(); - }, - lineStart: function() { - this._curve.lineStart(); - }, - lineEnd: function() { - this._curve.lineEnd(); - }, - point: function(a, r) { - this._curve.point(r * Math.sin(a), r * -Math.cos(a)); - } -}; - -function curveRadial(curve) { - - function radial(context) { - return new Radial(curve(context)); - } - - radial._curve = curve; - - return radial; -} - -function radialLine(l) { - var c = l.curve; - - l.angle = l.x, delete l.x; - l.radius = l.y, delete l.y; - - l.curve = function(_) { - return arguments.length ? c(curveRadial(_)) : c()._curve; - }; - - return l; -} - -var radialLine$1 = function() { - return radialLine(line().curve(curveRadialLinear)); -}; - -var radialArea = function() { - var a = area$1().curve(curveRadialLinear), - c = a.curve, - x0 = a.lineX0, - x1 = a.lineX1, - y0 = a.lineY0, - y1 = a.lineY1; - - a.angle = a.x, delete a.x; - a.startAngle = a.x0, delete a.x0; - a.endAngle = a.x1, delete a.x1; - a.radius = a.y, delete a.y; - a.innerRadius = a.y0, delete a.y0; - a.outerRadius = a.y1, delete a.y1; - a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0; - a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1; - a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0; - a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1; - - a.curve = function(_) { - return arguments.length ? c(curveRadial(_)) : c()._curve; - }; - - return a; -}; - -var circle = { - draw: function(context, size) { - var r = Math.sqrt(size / pi$2); - context.moveTo(r, 0); - context.arc(0, 0, r, 0, tau$2); - } -}; - -var cross$1 = { - draw: function(context, size) { - var r = Math.sqrt(size / 5) / 2; - context.moveTo(-3 * r, -r); - context.lineTo(-r, -r); - context.lineTo(-r, -3 * r); - context.lineTo(r, -3 * r); - context.lineTo(r, -r); - context.lineTo(3 * r, -r); - context.lineTo(3 * r, r); - context.lineTo(r, r); - context.lineTo(r, 3 * r); - context.lineTo(-r, 3 * r); - context.lineTo(-r, r); - context.lineTo(-3 * r, r); - context.closePath(); - } -}; - -var tan30 = Math.sqrt(1 / 3); -var tan30_2 = tan30 * 2; - -var diamond = { - draw: function(context, size) { - var y = Math.sqrt(size / tan30_2), - x = y * tan30; - context.moveTo(0, -y); - context.lineTo(x, 0); - context.lineTo(0, y); - context.lineTo(-x, 0); - context.closePath(); - } -}; - -var ka = 0.89081309152928522810; -var kr = Math.sin(pi$2 / 10) / Math.sin(7 * pi$2 / 10); -var kx = Math.sin(tau$2 / 10) * kr; -var ky = -Math.cos(tau$2 / 10) * kr; - -var star = { - draw: function(context, size) { - var r = Math.sqrt(size * ka), - x = kx * r, - y = ky * r; - context.moveTo(0, -r); - context.lineTo(x, y); - for (var i = 1; i < 5; ++i) { - var a = tau$2 * i / 5, - c = Math.cos(a), - s = Math.sin(a); - context.lineTo(s * r, -c * r); - context.lineTo(c * x - s * y, s * x + c * y); - } - context.closePath(); - } -}; - -var square = { - draw: function(context, size) { - var w = Math.sqrt(size), - x = -w / 2; - context.rect(x, x, w, w); - } -}; - -var sqrt3 = Math.sqrt(3); - -var triangle = { - draw: function(context, size) { - var y = -Math.sqrt(size / (sqrt3 * 3)); - context.moveTo(0, y * 2); - context.lineTo(-sqrt3 * y, -y); - context.lineTo(sqrt3 * y, -y); - context.closePath(); - } -}; - -var c = -0.5; -var s = Math.sqrt(3) / 2; -var k = 1 / Math.sqrt(12); -var a = (k / 2 + 1) * 3; - -var wye = { - draw: function(context, size) { - var r = Math.sqrt(size / a), - x0 = r / 2, - y0 = r * k, - x1 = x0, - y1 = r * k + r, - x2 = -x1, - y2 = y1; - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - context.lineTo(c * x0 - s * y0, s * x0 + c * y0); - context.lineTo(c * x1 - s * y1, s * x1 + c * y1); - context.lineTo(c * x2 - s * y2, s * x2 + c * y2); - context.lineTo(c * x0 + s * y0, c * y0 - s * x0); - context.lineTo(c * x1 + s * y1, c * y1 - s * x1); - context.lineTo(c * x2 + s * y2, c * y2 - s * x2); - context.closePath(); - } -}; - -var symbols = [ - circle, - cross$1, - diamond, - square, - star, - triangle, - wye -]; - -var symbol = function() { - var type = constant$2(circle), - size = constant$2(64), - context = null; - - function symbol() { - var buffer; - if (!context) context = buffer = path(); - type.apply(this, arguments).draw(context, +size.apply(this, arguments)); - if (buffer) return context = null, buffer + "" || null; - } - - symbol.type = function(_) { - return arguments.length ? (type = typeof _ === "function" ? _ : constant$2(_), symbol) : type; - }; - - symbol.size = function(_) { - return arguments.length ? (size = typeof _ === "function" ? _ : constant$2(+_), symbol) : size; - }; - - symbol.context = function(_) { - return arguments.length ? (context = _ == null ? null : _, symbol) : context; - }; - - return symbol; -}; - -var noop = function() {}; - -function point(that, x, y) { - that._context.bezierCurveTo( - (2 * that._x0 + that._x1) / 3, - (2 * that._y0 + that._y1) / 3, - (that._x0 + 2 * that._x1) / 3, - (that._y0 + 2 * that._y1) / 3, - (that._x0 + 4 * that._x1 + x) / 6, - (that._y0 + 4 * that._y1 + y) / 6 - ); -} - -function Basis(context) { - this._context = context; -} - -Basis.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 3: point(this, this._x1, this._y1); // proceed - case 2: this._context.lineTo(this._x1, this._y1); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed - default: point(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -var basis = function(context) { - return new Basis(context); -}; - -function BasisClosed(context) { - this._context = context; -} - -BasisClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x2, this._y2); - this._context.closePath(); - break; - } - case 2: { - this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); - this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x2, this._y2); - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._x2 = x, this._y2 = y; break; - case 1: this._point = 2; this._x3 = x, this._y3 = y; break; - case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; - default: point(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -var basisClosed = function(context) { - return new BasisClosed(context); -}; - -function BasisOpen(context) { - this._context = context; -} - -BasisOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = NaN; - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; - case 3: this._point = 4; // proceed - default: point(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -var basisOpen = function(context) { - return new BasisOpen(context); -}; - -function Bundle(context, beta) { - this._basis = new Basis(context); - this._beta = beta; -} - -Bundle.prototype = { - lineStart: function() { - this._x = []; - this._y = []; - this._basis.lineStart(); - }, - lineEnd: function() { - var x = this._x, - y = this._y, - j = x.length - 1; - - if (j > 0) { - var x0 = x[0], - y0 = y[0], - dx = x[j] - x0, - dy = y[j] - y0, - i = -1, - t; - - while (++i <= j) { - t = i / j; - this._basis.point( - this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), - this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) - ); - } - } - - this._x = this._y = null; - this._basis.lineEnd(); - }, - point: function(x, y) { - this._x.push(+x); - this._y.push(+y); - } -}; - -var bundle = (function custom(beta) { - - function bundle(context) { - return beta === 1 ? new Basis(context) : new Bundle(context, beta); - } - - bundle.beta = function(beta) { - return custom(+beta); - }; - - return bundle; -})(0.85); - -function point$1(that, x, y) { - that._context.bezierCurveTo( - that._x1 + that._k * (that._x2 - that._x0), - that._y1 + that._k * (that._y2 - that._y0), - that._x2 + that._k * (that._x1 - x), - that._y2 + that._k * (that._y1 - y), - that._x2, - that._y2 - ); -} - -function Cardinal(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -Cardinal.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x2, this._y2); break; - case 3: point$1(this, this._x1, this._y1); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; this._x1 = x, this._y1 = y; break; - case 2: this._point = 3; // proceed - default: point$1(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinal = (function custom(tension) { - - function cardinal(context) { - return new Cardinal(context, tension); - } - - cardinal.tension = function(tension) { - return custom(+tension); - }; - - return cardinal; -})(0); - -function CardinalClosed(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -CardinalClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 2: { - this._context.lineTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - this.point(this._x5, this._y5); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._x3 = x, this._y3 = y; break; - case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; - case 2: this._point = 3; this._x5 = x, this._y5 = y; break; - default: point$1(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } +var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 }; -var cardinalClosed = (function custom(tension) { - - function cardinal(context) { - return new CardinalClosed(context, tension); - } - - cardinal.tension = function(tension) { - return custom(+tension); - }; - - return cardinal; -})(0); - -function CardinalOpen(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -CardinalOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; +define(Color, color, { + displayable: function() { + return this.rgb().displayable(); }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; - case 3: this._point = 4; // proceed - default: point$1(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinalOpen = (function custom(tension) { - - function cardinal(context) { - return new CardinalOpen(context, tension); + toString: function() { + return this.rgb() + ""; } +}); - cardinal.tension = function(tension) { - return custom(+tension); - }; - - return cardinal; -})(0); +function color(format) { + var m; + format = (format + "").trim().toLowerCase(); + return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 + : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; +} -function point$2(that, x, y) { - var x1 = that._x1, - y1 = that._y1, - x2 = that._x2, - y2 = that._y2; +function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); +} - if (that._l01_a > epsilon$1) { - var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, - n = 3 * that._l01_a * (that._l01_a + that._l12_a); - x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; - y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; - } +function rgba(r, g, b, a) { + if (a <= 0) r = g = b = NaN; + return new Rgb(r, g, b, a); +} - if (that._l23_a > epsilon$1) { - var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, - m = 3 * that._l23_a * (that._l23_a + that._l12_a); - x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; - y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; - } +function rgbConvert(o) { + if (!(o instanceof Color)) o = color(o); + if (!o) return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); +} - that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); +function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); } -function CatmullRom(context, alpha) { - this._context = context; - this._alpha = alpha; +function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; } -CatmullRom.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; +define(Rgb, rgb, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x2, this._y2); break; - case 3: this.point(this._x2, this._y2); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; // proceed - default: point$2(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var catmullRom = (function custom(alpha) { - - function catmullRom(context) { - return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); - } - - catmullRom.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom; -})(0.5); - -function CatmullRomClosed(context, alpha) { - this._context = context; - this._alpha = alpha; -} - -CatmullRomClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; + rgb: function() { + return this; }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 2: { - this._context.lineTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - this.point(this._x5, this._y5); - break; - } - } + displayable: function() { + return (0 <= this.r && this.r <= 255) + && (0 <= this.g && this.g <= 255) + && (0 <= this.b && this.b <= 255) + && (0 <= this.opacity && this.opacity <= 1); }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; this._x3 = x, this._y3 = y; break; - case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; - case 2: this._point = 3; this._x5 = x, this._y5 = y; break; - default: point$2(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + toString: function() { + var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "rgb(" : "rgba(") + + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + + (a === 1 ? ")" : ", " + a + ")"); } -}; +})); -var catmullRomClosed = (function custom(alpha) { +function hsla(h, s, l, a) { + if (a <= 0) h = s = l = NaN; + else if (l <= 0 || l >= 1) h = s = NaN; + else if (s <= 0) h = NaN; + return new Hsl(h, s, l, a); +} - function catmullRom(context) { - return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); +function hslConvert(o) { + if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) o = color(o); + if (!o) return new Hsl; + if (o instanceof Hsl) return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) h = (g - b) / s + (g < b) * 6; + else if (g === max) h = (b - r) / s + 2; + else h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; } + return new Hsl(h, s, l, o.opacity); +} - catmullRom.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom; -})(0.5); +function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); +} -function CatmullRomOpen(context, alpha) { - this._context = context; - this._alpha = alpha; +function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; } -CatmullRomOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; +define(Hsl, hsl, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; + rgb: function() { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } + displayable: function() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + } +})); - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; - case 3: this._point = 4; // proceed - default: point$2(this, x, y); break; - } +/* From FvD 13.37, CSS Color Module Level 3 */ +function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; +} - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; +var deg2rad = Math.PI / 180; +var rad2deg = 180 / Math.PI; -var catmullRomOpen = (function custom(alpha) { +var Kn = 18; +var Xn = 0.950470; +var Yn = 1; +var Zn = 1.088830; +var t0 = 4 / 29; +var t1 = 6 / 29; +var t2 = 3 * t1 * t1; +var t3 = t1 * t1 * t1; - function catmullRom(context) { - return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); +function labConvert(o) { + if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); + if (o instanceof Hcl) { + var h = o.h * deg2rad; + return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); } + if (!(o instanceof Rgb)) o = rgbConvert(o); + var b = rgb2xyz(o.r), + a = rgb2xyz(o.g), + l = rgb2xyz(o.b), + x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), + y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), + z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); + return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); +} - catmullRom.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom; -})(0.5); +function lab(l, a, b, opacity) { + return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); +} -function LinearClosed(context) { - this._context = context; +function Lab(l, a, b, opacity) { + this.l = +l; + this.a = +a; + this.b = +b; + this.opacity = +opacity; } -LinearClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._point = 0; +define(Lab, lab, extend(Color, { + brighter: function(k) { + return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); }, - lineEnd: function() { - if (this._point) this._context.closePath(); + darker: function(k) { + return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); }, - point: function(x, y) { - x = +x, y = +y; - if (this._point) this._context.lineTo(x, y); - else this._point = 1, this._context.moveTo(x, y); + rgb: function() { + var y = (this.l + 16) / 116, + x = isNaN(this.a) ? y : y + this.a / 500, + z = isNaN(this.b) ? y : y - this.b / 200; + y = Yn * lab2xyz(y); + x = Xn * lab2xyz(x); + z = Zn * lab2xyz(z); + return new Rgb( + xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB + xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), + xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), + this.opacity + ); } -}; +})); -var linearClosed = function(context) { - return new LinearClosed(context); -}; +function xyz2lab(t) { + return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; +} -function sign(x) { - return x < 0 ? -1 : 1; +function lab2xyz(t) { + return t > t1 ? t * t * t : t2 * (t - t0); } -// Calculate the slopes of the tangents (Hermite-type interpolation) based on -// the following paper: Steffen, M. 1990. A Simple Method for Monotonic -// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. -// NOV(II), P. 443, 1990. -function slope3(that, x2, y2) { - var h0 = that._x1 - that._x0, - h1 = x2 - that._x1, - s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), - s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), - p = (s0 * h1 + s1 * h0) / (h0 + h1); - return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; +function xyz2rgb(x) { + return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); +} + +function rgb2xyz(x) { + return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); +} + +function hclConvert(o) { + if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); + if (!(o instanceof Lab)) o = labConvert(o); + var h = Math.atan2(o.b, o.a) * rad2deg; + return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); +} + +function hcl(h, c, l, opacity) { + return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); +} + +function Hcl(h, c, l, opacity) { + this.h = +h; + this.c = +c; + this.l = +l; + this.opacity = +opacity; } -// Calculate a one-sided slope. -function slope2(that, t) { - var h = that._x1 - that._x0; - return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; +define(Hcl, hcl, extend(Color, { + brighter: function(k) { + return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); + }, + darker: function(k) { + return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); + }, + rgb: function() { + return labConvert(this).rgb(); + } +})); + +var A = -0.14861; +var B = +1.78277; +var C = -0.29227; +var D = -0.90649; +var E = +1.97294; +var ED = E * D; +var EB = E * B; +var BC_DA = B * C - D * A; + +function cubehelixConvert(o) { + if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Rgb)) o = rgbConvert(o); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), + bl = b - l, + k = (E * (g - l) - C * bl) / D, + s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 + h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; + return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); } -// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations -// "you can express cubic Hermite interpolation in terms of cubic Bézier curves -// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". -function point$3(that, t0, t1) { - var x0 = that._x0, - y0 = that._y0, - x1 = that._x1, - y1 = that._y1, - dx = (x1 - x0) / 3; - that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); +function cubehelix(h, s, l, opacity) { + return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); } -function MonotoneX(context) { - this._context = context; +function Cubehelix(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; } -MonotoneX.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = - this._t0 = NaN; - this._point = 0; +define(Cubehelix, cubehelix, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x1, this._y1); break; - case 3: point$3(this, this._t0, slope2(this, this._t0)); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); }, - point: function(x, y) { - var t1 = NaN; - - x = +x, y = +y; - if (x === this._x1 && y === this._y1) return; // Ignore coincident points. - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break; - default: point$3(this, this._t0, t1 = slope3(this, x, y)); break; - } - - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - this._t0 = t1; + rgb: function() { + var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, + l = +this.l, + a = isNaN(this.s) ? 0 : this.s * l * (1 - l), + cosh = Math.cos(h), + sinh = Math.sin(h); + return new Rgb( + 255 * (l + a * (A * cosh + B * sinh)), + 255 * (l + a * (C * cosh + D * sinh)), + 255 * (l + a * (E * cosh)), + this.opacity + ); } -}; +})); -function MonotoneY(context) { - this._context = new ReflectContext(context); +function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + + (4 - 6 * t2 + 3 * t3) * v1 + + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + + t3 * v3) / 6; } -(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { - MonotoneX.prototype.point.call(this, y, x); +var basis$1 = function(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), + v1 = values[i], + v2 = values[i + 1], + v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, + v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; }; -function ReflectContext(context) { - this._context = context; -} +var basisClosed = function(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), + v0 = values[(i + n - 1) % n], + v1 = values[i % n], + v2 = values[(i + 1) % n], + v3 = values[(i + 2) % n]; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +}; -ReflectContext.prototype = { - moveTo: function(x, y) { this._context.moveTo(y, x); }, - closePath: function() { this._context.closePath(); }, - lineTo: function(x, y) { this._context.lineTo(y, x); }, - bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } +var constant$3 = function(x) { + return function() { + return x; + }; }; -function monotoneX(context) { - return new MonotoneX(context); +function linear(a, d) { + return function(t) { + return a + t * d; + }; } -function monotoneY(context) { - return new MonotoneY(context); +function exponential(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { + return Math.pow(a + t * b, y); + }; } -function Natural(context) { - this._context = context; +function hue(a, b) { + var d = b - a; + return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a); } -Natural.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x = []; - this._y = []; - }, - lineEnd: function() { - var x = this._x, - y = this._y, - n = x.length; +function gamma(y) { + return (y = +y) === 1 ? nogamma : function(a, b) { + return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a); + }; +} - if (n) { - this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); - if (n === 2) { - this._context.lineTo(x[1], y[1]); - } else { - var px = controlPoints(x), - py = controlPoints(y); - for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { - this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); - } - } - } +function nogamma(a, b) { + var d = b - a; + return d ? linear(a, d) : constant$3(isNaN(a) ? b : a); +} - if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); - this._line = 1 - this._line; - this._x = this._y = null; - }, - point: function(x, y) { - this._x.push(+x); - this._y.push(+y); - } -}; +var interpolateRgb = ((function rgbGamma(y) { + var color$$1 = gamma(y); -// See https://www.particleincell.com/2012/bezier-splines/ for derivation. -function controlPoints(x) { - var i, - n = x.length - 1, - m, - a = new Array(n), - b = new Array(n), - r = new Array(n); - a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; - for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; - a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; - for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; - a[n - 1] = r[n - 1] / b[n - 1]; - for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; - b[n - 1] = (x[n] + a[n - 1]) / 2; - for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; - return [a, b]; -} + function rgb$$1(start, end) { + var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r), + g = color$$1(start.g, end.g), + b = color$$1(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } -var natural = function(context) { - return new Natural(context); -}; + rgb$$1.gamma = rgbGamma; -function Step(context, t) { - this._context = context; - this._t = t; -} + return rgb$$1; +}))(1); -Step.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x = this._y = NaN; - this._point = 0; - }, - lineEnd: function() { - if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; // proceed - default: { - if (this._t <= 0) { - this._context.lineTo(this._x, y); - this._context.lineTo(x, y); - } else { - var x1 = this._x * (1 - this._t) + x * this._t; - this._context.lineTo(x1, this._y); - this._context.lineTo(x1, y); - } - break; - } +function rgbSpline(spline) { + return function(colors) { + var n = colors.length, + r = new Array(n), + g = new Array(n), + b = new Array(n), + i, color$$1; + for (i = 0; i < n; ++i) { + color$$1 = rgb(colors[i]); + r[i] = color$$1.r || 0; + g[i] = color$$1.g || 0; + b[i] = color$$1.b || 0; } - this._x = x, this._y = y; - } + r = spline(r); + g = spline(g); + b = spline(b); + color$$1.opacity = 1; + return function(t) { + color$$1.r = r(t); + color$$1.g = g(t); + color$$1.b = b(t); + return color$$1 + ""; + }; + }; +} + +var rgbBasis = rgbSpline(basis$1); +var rgbBasisClosed = rgbSpline(basisClosed); + +var array$1 = function(a, b) { + var nb = b ? b.length : 0, + na = a ? Math.min(nb, a.length) : 0, + x = new Array(nb), + c = new Array(nb), + i; + + for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]); + for (; i < nb; ++i) c[i] = b[i]; + + return function(t) { + for (i = 0; i < na; ++i) c[i] = x[i](t); + return c; + }; }; -var step = function(context) { - return new Step(context, 0.5); +var date = function(a, b) { + var d = new Date; + return a = +a, b -= a, function(t) { + return d.setTime(a + b * t), d; + }; }; -function stepBefore(context) { - return new Step(context, 0); -} +var reinterpolate = function(a, b) { + return a = +a, b -= a, function(t) { + return a + b * t; + }; +}; -function stepAfter(context) { - return new Step(context, 1); -} +var object = function(a, b) { + var i = {}, + c = {}, + k; -var slice$2 = Array.prototype.slice; + if (a === null || typeof a !== "object") a = {}; + if (b === null || typeof b !== "object") b = {}; -var none = function(series, order) { - if (!((n = series.length) > 1)) return; - for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { - s0 = s1, s1 = series[order[i]]; - for (var j = 0; j < m; ++j) { - s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; + for (k in b) { + if (k in a) { + i[k] = interpolateValue(a[k], b[k]); + } else { + c[k] = b[k]; } } -}; -var none$1 = function(series) { - var n = series.length, o = new Array(n); - while (--n >= 0) o[n] = n; - return o; + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; }; -function stackValue(d, key) { - return d[key]; +var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; +var reB = new RegExp(reA.source, "g"); + +function zero(b) { + return function() { + return b; + }; } -var stack = function() { - var keys = constant$2([]), - order = none$1, - offset = none, - value = stackValue; +function one(b) { + return function(t) { + return b(t) + ""; + }; +} - function stack(data) { - var kz = keys.apply(this, arguments), - i, - m = data.length, - n = kz.length, - sz = new Array(n), - oz; +var interpolateString = function(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators - for (i = 0; i < n; ++i) { - for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { - si[j] = sij = [0, +value(data[j], ki, j, data)]; - sij.data = data[j]; - } - si.key = ki; - } + // Coerce inputs to strings. + a = a + "", b = b + ""; - for (i = 0, oz = order(sz); i < n; ++i) { - sz[oz[i]].index = i; + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) s[i] += bm; // coalesce with previous string + else s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: reinterpolate(am, bm)}); } + bi = reB.lastIndex; + } - offset(sz, oz); - return sz; + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; } - stack.keys = function(_) { - return arguments.length ? (keys = typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : keys; - }; + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(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(""); + }); +}; - stack.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), stack) : value; - }; +var interpolateValue = function(a, b) { + var t = typeof b, c; + return b == null || t === "boolean" ? constant$3(b) + : (t === "number" ? reinterpolate + : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString) + : b instanceof color ? interpolateRgb + : b instanceof Date ? date + : Array.isArray(b) ? array$1 + : isNaN(b) ? object + : reinterpolate)(a, b); +}; - stack.order = function(_) { - return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : order; +var interpolateRound = function(a, b) { + return a = +a, b -= a, function(t) { + return Math.round(a + b * t); }; +}; - stack.offset = function(_) { - return arguments.length ? (offset = _ == null ? none : _, stack) : offset; - }; +var degrees = 180 / Math.PI; - return stack; +var identity$2 = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 }; -var expand = function(series, order) { - if (!((n = series.length) > 0)) return; - for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { - for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; - if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; - } - none(series, order); +var decompose = function(a, b, c, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; + if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; + if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX: scaleX, + scaleY: scaleY + }; }; -var silhouette = function(series, order) { - if (!((n = series.length) > 0)) return; - for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { - for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; - s0[j][1] += s0[j][0] = -y / 2; +var cssNode; +var cssRoot; +var cssView; +var svgNode; + +function parseCss(value) { + if (value === "none") return identity$2; + if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; + cssNode.style.transform = value; + value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); + cssRoot.removeChild(cssNode); + value = value.slice(7, -1).split(","); + return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); +} + +function parseSvg(value) { + if (value == null) return identity$2; + if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2; + value = value.matrix; + return decompose(value.a, value.b, value.c, value.d, value.e, value.f); +} + +function interpolateTransform(parse, pxComma, pxParen, degParen) { + + function pop(s) { + return s.length ? s.pop() + " " : ""; } - none(series, order); -}; -var wiggle = function(series, order) { - if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; - for (var y = 0, j = 1, s0, m, n; j < m; ++j) { - for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { - var si = series[order[i]], - sij0 = si[j][1] || 0, - sij1 = si[j - 1][1] || 0, - s3 = (sij0 - sij1) / 2; - for (var k = 0; k < i; ++k) { - var sk = series[order[k]], - skj0 = sk[j][1] || 0, - skj1 = sk[j - 1][1] || 0; - s3 += skj0 - skj1; - } - s1 += sij0, s2 += s3 * sij0; + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); } - s0[j - 1][1] += s0[j - 1][0] = y; - if (s1) y -= s2 / s1; } - s0[j - 1][1] += s0[j - 1][0] = y; - none(series, order); -}; - -var ascending$1 = function(series) { - var sums = series.map(sum$1); - return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; }); -}; - -function sum$1(series) { - var s = 0, i = -1, n = series.length, v; - while (++i < n) if (v = +series[i][1]) s += v; - return s; -} -var descending$2 = function(series) { - return ascending$1(series).reverse(); -}; + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: reinterpolate(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } -var insideOut = function(series) { - var n = series.length, - i, - j, - sums = series.map(sum$1), - order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }), - top = 0, - bottom = 0, - tops = [], - bottoms = []; + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: reinterpolate(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } - for (i = 0; i < n; ++i) { - j = order[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); } } - return bottoms.reverse().concat(tops); -}; + return function(a, b) { + var s = [], // string constants and placeholders + q = []; // number interpolators + a = parse(a), b = parse(b); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); + rotate(a.rotate, b.rotate, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); + a = b = null; // gc + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; +} -var reverse = function(series) { - return none$1(series).reverse(); -}; +var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); +var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); -var define = function(constructor, factory, prototype) { - constructor.prototype = factory.prototype = prototype; - prototype.constructor = constructor; -}; +var rho = Math.SQRT2; +var rho2 = 2; +var rho4 = 4; +var epsilon2 = 1e-12; -function extend(parent, definition) { - var prototype = Object.create(parent.prototype); - for (var key in definition) prototype[key] = definition[key]; - return prototype; +function cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; } -function Color() {} +function sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; +} -var darker = 0.7; -var brighter = 1 / darker; +function tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); +} -var reHex3 = /^#([0-9a-f]{3})$/; -var reHex6 = /^#([0-9a-f]{6})$/; -var reRgbInteger = /^rgb\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*\)$/; -var reRgbPercent = /^rgb\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/; -var reRgbaInteger = /^rgba\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/; -var reRgbaPercent = /^rgba\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/; -var reHslPercent = /^hsl\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/; -var reHslaPercent = /^hsla\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/; +// p0 = [ux0, uy0, w0] +// p1 = [ux1, uy1, w1] +var 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; -var named = { - aliceblue: 0xf0f8ff, - antiquewhite: 0xfaebd7, - aqua: 0x00ffff, - aquamarine: 0x7fffd4, - azure: 0xf0ffff, - beige: 0xf5f5dc, - bisque: 0xffe4c4, - black: 0x000000, - blanchedalmond: 0xffebcd, - blue: 0x0000ff, - blueviolet: 0x8a2be2, - brown: 0xa52a2a, - burlywood: 0xdeb887, - cadetblue: 0x5f9ea0, - chartreuse: 0x7fff00, - chocolate: 0xd2691e, - coral: 0xff7f50, - cornflowerblue: 0x6495ed, - cornsilk: 0xfff8dc, - crimson: 0xdc143c, - cyan: 0x00ffff, - darkblue: 0x00008b, - darkcyan: 0x008b8b, - darkgoldenrod: 0xb8860b, - darkgray: 0xa9a9a9, - darkgreen: 0x006400, - darkgrey: 0xa9a9a9, - darkkhaki: 0xbdb76b, - darkmagenta: 0x8b008b, - darkolivegreen: 0x556b2f, - darkorange: 0xff8c00, - darkorchid: 0x9932cc, - darkred: 0x8b0000, - darksalmon: 0xe9967a, - darkseagreen: 0x8fbc8f, - darkslateblue: 0x483d8b, - darkslategray: 0x2f4f4f, - darkslategrey: 0x2f4f4f, - darkturquoise: 0x00ced1, - darkviolet: 0x9400d3, - deeppink: 0xff1493, - deepskyblue: 0x00bfff, - dimgray: 0x696969, - dimgrey: 0x696969, - dodgerblue: 0x1e90ff, - firebrick: 0xb22222, - floralwhite: 0xfffaf0, - forestgreen: 0x228b22, - fuchsia: 0xff00ff, - gainsboro: 0xdcdcdc, - ghostwhite: 0xf8f8ff, - gold: 0xffd700, - goldenrod: 0xdaa520, - gray: 0x808080, - green: 0x008000, - greenyellow: 0xadff2f, - grey: 0x808080, - honeydew: 0xf0fff0, - hotpink: 0xff69b4, - indianred: 0xcd5c5c, - indigo: 0x4b0082, - ivory: 0xfffff0, - khaki: 0xf0e68c, - lavender: 0xe6e6fa, - lavenderblush: 0xfff0f5, - lawngreen: 0x7cfc00, - lemonchiffon: 0xfffacd, - lightblue: 0xadd8e6, - lightcoral: 0xf08080, - lightcyan: 0xe0ffff, - lightgoldenrodyellow: 0xfafad2, - lightgray: 0xd3d3d3, - lightgreen: 0x90ee90, - lightgrey: 0xd3d3d3, - lightpink: 0xffb6c1, - lightsalmon: 0xffa07a, - lightseagreen: 0x20b2aa, - lightskyblue: 0x87cefa, - lightslategray: 0x778899, - lightslategrey: 0x778899, - lightsteelblue: 0xb0c4de, - lightyellow: 0xffffe0, - lime: 0x00ff00, - limegreen: 0x32cd32, - linen: 0xfaf0e6, - magenta: 0xff00ff, - maroon: 0x800000, - mediumaquamarine: 0x66cdaa, - mediumblue: 0x0000cd, - mediumorchid: 0xba55d3, - mediumpurple: 0x9370db, - mediumseagreen: 0x3cb371, - mediumslateblue: 0x7b68ee, - mediumspringgreen: 0x00fa9a, - mediumturquoise: 0x48d1cc, - mediumvioletred: 0xc71585, - midnightblue: 0x191970, - mintcream: 0xf5fffa, - mistyrose: 0xffe4e1, - moccasin: 0xffe4b5, - navajowhite: 0xffdead, - navy: 0x000080, - oldlace: 0xfdf5e6, - olive: 0x808000, - olivedrab: 0x6b8e23, - orange: 0xffa500, - orangered: 0xff4500, - orchid: 0xda70d6, - palegoldenrod: 0xeee8aa, - palegreen: 0x98fb98, - paleturquoise: 0xafeeee, - palevioletred: 0xdb7093, - papayawhip: 0xffefd5, - peachpuff: 0xffdab9, - peru: 0xcd853f, - pink: 0xffc0cb, - plum: 0xdda0dd, - powderblue: 0xb0e0e6, - purple: 0x800080, - rebeccapurple: 0x663399, - red: 0xff0000, - rosybrown: 0xbc8f8f, - royalblue: 0x4169e1, - saddlebrown: 0x8b4513, - salmon: 0xfa8072, - sandybrown: 0xf4a460, - seagreen: 0x2e8b57, - seashell: 0xfff5ee, - sienna: 0xa0522d, - silver: 0xc0c0c0, - skyblue: 0x87ceeb, - slateblue: 0x6a5acd, - slategray: 0x708090, - slategrey: 0x708090, - snow: 0xfffafa, - springgreen: 0x00ff7f, - steelblue: 0x4682b4, - tan: 0xd2b48c, - teal: 0x008080, - thistle: 0xd8bfd8, - tomato: 0xff6347, - turquoise: 0x40e0d0, - violet: 0xee82ee, - wheat: 0xf5deb3, - white: 0xffffff, - whitesmoke: 0xf5f5f5, - yellow: 0xffff00, - yellowgreen: 0x9acd32 + // Special case for u0 ≅ u1. + if (d2 < epsilon2) { + S = Math.log(w1 / w0) / rho; + i = function(t) { + return [ + ux0 + t * dx, + uy0 + t * dy, + w0 * Math.exp(rho * t * S) + ]; + }; + } + + // General case. + else { + var d1 = Math.sqrt(d2), + b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), + b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), + r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), + r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / rho; + i = function(t) { + var s = t * S, + coshr0 = cosh(r0), + u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); + return [ + ux0 + u * dx, + uy0 + u * dy, + w0 * coshr0 / cosh(rho * s + r0) + ]; + }; + } + + i.duration = S * 1000; + + return i; }; -define(Color, color, { - displayable: function() { - return this.rgb().displayable(); - }, - toString: function() { - return this.rgb() + ""; +function hsl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; } -}); +} -function color(format) { - var m; - format = (format + "").trim().toLowerCase(); - return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 - : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 - : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) - : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) - : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) - : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) - : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) - : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) - : named.hasOwnProperty(format) ? rgbn(named[format]) - : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) - : null; +var hsl$2 = hsl$1(hue); +var hslLong = hsl$1(nogamma); + +function lab$1(start, end) { + var l = nogamma((start = lab(start)).l, (end = lab(end)).l), + a = nogamma(start.a, end.a), + b = nogamma(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.l = l(t); + start.a = a(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; } -function rgbn(n) { - return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); +function hcl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h), + c = nogamma(start.c, end.c), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.c = c(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } } -function rgba(r, g, b, a) { - if (a <= 0) r = g = b = NaN; - return new Rgb(r, g, b, a); +var hcl$2 = hcl$1(hue); +var hclLong = hcl$1(nogamma); + +function cubehelix$1(hue$$1) { + return (function cubehelixGamma(y) { + y = +y; + + function cubehelix$$1(start, end) { + var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(Math.pow(t, y)); + start.opacity = opacity(t); + return start + ""; + }; + } + + cubehelix$$1.gamma = cubehelixGamma; + + return cubehelix$$1; + })(1); } -function rgbConvert(o) { - if (!(o instanceof Color)) o = color(o); - if (!o) return new Rgb; - o = o.rgb(); - return new Rgb(o.r, o.g, o.b, o.opacity); +var cubehelix$2 = cubehelix$1(hue); +var cubehelixLong = cubehelix$1(nogamma); + +var quantize = function(interpolator, n) { + var samples = new Array(n); + for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); + return samples; +}; + +var frame = 0; +var timeout = 0; +var interval = 0; +var pokeDelay = 1000; +var taskHead; +var taskTail; +var clockLast = 0; +var clockNow = 0; +var clockSkew = 0; +var clock = typeof performance === "object" && performance.now ? performance : Date; +var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); }; + +function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); } -function rgb(r, g, b, opacity) { - return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); +function clearNow() { + clockNow = 0; } -function Rgb(r, g, b, opacity) { - this.r = +r; - this.g = +g; - this.b = +b; - this.opacity = +opacity; +function Timer() { + this._call = + this._time = + this._next = null; } -define(Rgb, rgb, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - rgb: function() { - return this; - }, - displayable: function() { - return (0 <= this.r && this.r <= 255) - && (0 <= this.g && this.g <= 255) - && (0 <= this.b && this.b <= 255) - && (0 <= this.opacity && this.opacity <= 1); +Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) taskTail._next = this; + else taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); }, - toString: function() { - var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); - return (a === 1 ? "rgb(" : "rgba(") - + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.b) || 0)) - + (a === 1 ? ")" : ", " + a + ")"); + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } } -})); +}; -function hsla(h, s, l, a) { - if (a <= 0) h = s = l = NaN; - else if (l <= 0 || l >= 1) h = s = NaN; - else if (s <= 0) h = NaN; - return new Hsl(h, s, l, a); +function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; } -function hslConvert(o) { - if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Color)) o = color(o); - if (!o) return new Hsl; - if (o instanceof Hsl) return o; - o = o.rgb(); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - h = NaN, - s = max - min, - l = (max + min) / 2; - if (s) { - if (r === max) h = (g - b) / s + (g < b) * 6; - else if (g === max) h = (b - r) / s + 2; - else h = (r - g) / s + 4; - s /= l < 0.5 ? max + min : 2 - max - min; - h *= 60; - } else { - s = l > 0 && l < 1 ? 0 : h; +function timerFlush() { + now(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) t._call.call(null, e); + t = t._next; + } + --frame; +} + +function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; } - return new Hsl(h, s, l, o.opacity); } -function hsl(h, s, l, opacity) { - return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); +function poke() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) clockSkew -= delay, clockLast = now; } -function Hsl(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; +function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); } -define(Hsl, hsl, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = this.h % 360 + (this.h < 0) * 360, - s = isNaN(h) || isNaN(this.s) ? 0 : this.s, - l = this.l, - m2 = l + (l < 0.5 ? l : 1 - l) * s, - m1 = 2 * l - m2; - return new Rgb( - hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), - hsl2rgb(h, m1, m2), - hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), - this.opacity - ); - }, - displayable: function() { - return (0 <= this.s && this.s <= 1 || isNaN(this.s)) - && (0 <= this.l && this.l <= 1) - && (0 <= this.opacity && this.opacity <= 1); +function sleep(time) { + if (frame) return; // Soonest alarm already set, or will be. + if (timeout) timeout = clearTimeout(timeout); + var delay = time - clockNow; + if (delay > 24) { + if (time < Infinity) timeout = setTimeout(wake, delay); + if (interval) interval = clearInterval(interval); + } else { + if (!interval) clockLast = clockNow, interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); } -})); - -/* From FvD 13.37, CSS Color Module Level 3 */ -function hsl2rgb(h, m1, m2) { - return (h < 60 ? m1 + (m2 - m1) * h / 60 - : h < 180 ? m2 - : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 - : m1) * 255; } -var deg2rad = Math.PI / 180; -var rad2deg = 180 / Math.PI; +var timeout$1 = function(callback, delay, time) { + var t = new Timer; + delay = delay == null ? 0 : +delay; + t.restart(function(elapsed) { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; +}; -var Kn = 18; -var Xn = 0.950470; -var Yn = 1; -var Zn = 1.088830; -var t0 = 4 / 29; -var t1 = 6 / 29; -var t2 = 3 * t1 * t1; -var t3 = t1 * t1 * t1; +var interval$1 = function(callback, delay, time) { + var t = new Timer, total = delay; + if (delay == null) return t.restart(callback, delay, time), t; + delay = +delay, time = time == null ? now() : +time; + t.restart(function tick(elapsed) { + elapsed += total; + t.restart(tick, total += delay, time); + callback(elapsed); + }, delay, time); + return t; +}; -function labConvert(o) { - if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); - if (o instanceof Hcl) { - var h = o.h * deg2rad; - return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); - } - if (!(o instanceof Rgb)) o = rgbConvert(o); - var b = rgb2xyz(o.r), - a = rgb2xyz(o.g), - l = rgb2xyz(o.b), - x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), - y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), - z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); - return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); +var emptyOn = dispatch("start", "end", "interrupt"); +var emptyTween = []; + +var CREATED = 0; +var SCHEDULED = 1; +var STARTING = 2; +var STARTED = 3; +var RUNNING = 4; +var ENDING = 5; +var ENDED = 6; + +var schedule = function(node, name, id, index, group, timing) { + var schedules = node.__transition; + if (!schedules) node.__transition = {}; + else if (id in schedules) return; + create(node, id, { + name: name, + index: index, // For context during callback. + group: group, // For context during callback. + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); +}; + +function init(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late"); + return schedule; } -function lab(l, a, b, opacity) { - return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); +function set$1(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); + return schedule; } -function Lab(l, a, b, opacity) { - this.l = +l; - this.a = +a; - this.b = +b; - this.opacity = +opacity; +function get$1(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id])) throw new Error("too late"); + return schedule; } -define(Lab, lab, extend(Color, { - brighter: function(k) { - return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - darker: function(k) { - return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - rgb: function() { - var y = (this.l + 16) / 116, - x = isNaN(this.a) ? y : y + this.a / 500, - z = isNaN(this.b) ? y : y - this.b / 200; - y = Yn * lab2xyz(y); - x = Xn * lab2xyz(x); - z = Zn * lab2xyz(z); - return new Rgb( - xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB - xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), - xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), - this.opacity - ); +function create(node, id, self) { + var schedules = node.__transition, + tween; + + // Initialize the self timer when the transition is created. + // Note the actual delay is not known until the first callback! + schedules[id] = self; + self.timer = timer(schedule, 0, self.time); + + function schedule(elapsed) { + self.state = SCHEDULED; + self.timer.restart(start, self.delay, self.time); + + // If the elapsed delay is less than our first sleep, start immediately. + if (self.delay <= elapsed) start(elapsed - self.delay); } -})); -function xyz2lab(t) { - return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; -} + function start(elapsed) { + var i, j, n, o; -function lab2xyz(t) { - return t > t1 ? t * t * t : t2 * (t - t0); -} + // If the state is not SCHEDULED, then we previously errored on start. + if (self.state !== SCHEDULED) return stop(); -function xyz2rgb(x) { - return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); -} + for (i in schedules) { + o = schedules[i]; + if (o.name !== self.name) continue; -function rgb2xyz(x) { - return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); -} + // While this element already has a starting transition during this frame, + // defer starting an interrupting transition until that transition has a + // chance to tick (and possibly end); see d3/d3-transition#54! + if (o.state === STARTED) return timeout$1(start); + + // Interrupt the active transition, if any. + // Dispatch the interrupt event. + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + + // Cancel any pre-empted transitions. No interrupt event is dispatched + // because the cancelled transitions never started. Note that this also + // removes this transition from the pending list! + else if (+i < id) { + o.state = ENDED; + o.timer.stop(); + delete schedules[i]; + } + } + + // Defer the first tick to end of the current frame; see d3/d3#1576. + // Note the transition may be canceled after start and before the first tick! + // Note this must be scheduled before the start event; see d3/d3-transition#16! + // Assuming this is successful, subsequent callbacks go straight to tick. + timeout$1(function() { + if (self.state === STARTED) { + self.state = RUNNING; + self.timer.restart(tick, self.delay, self.time); + tick(elapsed); + } + }); -function hclConvert(o) { - if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); - if (!(o instanceof Lab)) o = labConvert(o); - var h = Math.atan2(o.b, o.a) * rad2deg; - return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); -} + // Dispatch the start event. + // Note this must be done before the tween are initialized. + self.state = STARTING; + self.on.call("start", node, node.__data__, self.index, self.group); + if (self.state !== STARTING) return; // interrupted + self.state = STARTED; -function hcl(h, c, l, opacity) { - return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); -} + // Initialize the tween, deleting null tween. + tween = new Array(n = self.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } -function Hcl(h, c, l, opacity) { - this.h = +h; - this.c = +c; - this.l = +l; - this.opacity = +opacity; -} + function tick(elapsed) { + var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), + i = -1, + n = tween.length; -define(Hcl, hcl, extend(Color, { - brighter: function(k) { - return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); - }, - darker: function(k) { - return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); - }, - rgb: function() { - return labConvert(this).rgb(); - } -})); + while (++i < n) { + tween[i].call(null, t); + } -var A = -0.14861; -var B = +1.78277; -var C = -0.29227; -var D = -0.90649; -var E = +1.97294; -var ED = E * D; -var EB = E * B; -var BC_DA = B * C - D * A; + // Dispatch the end event. + if (self.state === ENDING) { + self.on.call("end", node, node.__data__, self.index, self.group); + stop(); + } + } -function cubehelixConvert(o) { - if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Rgb)) o = rgbConvert(o); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), - bl = b - l, - k = (E * (g - l) - C * bl) / D, - s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 - h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; - return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); + function stop() { + self.state = ENDED; + self.timer.stop(); + delete schedules[id]; + for (var i in schedules) return; // eslint-disable-line no-unused-vars + delete node.__transition; + } } -function cubehelix(h, s, l, opacity) { - return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); -} +var interrupt = function(node, name) { + var schedules = node.__transition, + schedule, + active, + empty = true, + i; -function Cubehelix(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; -} + if (!schedules) return; -define(Cubehelix, cubehelix, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, - l = +this.l, - a = isNaN(this.s) ? 0 : this.s * l * (1 - l), - cosh = Math.cos(h), - sinh = Math.sin(h); - return new Rgb( - 255 * (l + a * (A * cosh + B * sinh)), - 255 * (l + a * (C * cosh + D * sinh)), - 255 * (l + a * (E * cosh)), - this.opacity - ); - } -})); + name = name == null ? null : name + ""; -function basis$1(t1, v0, v1, v2, v3) { - var t2 = t1 * t1, t3 = t2 * t1; - return ((1 - 3 * t1 + 3 * t2 - t3) * v0 - + (4 - 6 * t2 + 3 * t3) * v1 - + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 - + t3 * v3) / 6; -} + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { empty = false; continue; } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } -var basis$2 = function(values) { - var n = values.length - 1; - return function(t) { - var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), - v1 = values[i], - v2 = values[i + 1], - v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, - v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; - return basis$1((t - i / n) * n, v0, v1, v2, v3); - }; + if (empty) delete node.__transition; }; -var basisClosed$1 = function(values) { - var n = values.length; - return function(t) { - var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), - v0 = values[(i + n - 1) % n], - v1 = values[i % n], - v2 = values[(i + 1) % n], - v3 = values[(i + 2) % n]; - return basis$1((t - i / n) * n, v0, v1, v2, v3); - }; +var selection_interrupt = function(name) { + return this.each(function() { + interrupt(this, name); + }); }; -var constant$3 = function(x) { +function tweenRemove(id, name) { + var tween0, tween1; return function() { - return x; - }; -}; - -function linear$1(a, d) { - return function(t) { - return a + t * d; - }; -} - -function exponential$1(a, b, y) { - return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { - return Math.pow(a + t * b, y); - }; -} + var schedule = set$1(this, id), + tween = schedule.tween; -function hue(a, b) { - var d = b - a; - return d ? linear$1(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a); -} + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } -function gamma(y) { - return (y = +y) === 1 ? nogamma : function(a, b) { - return b - a ? exponential$1(a, b, y) : constant$3(isNaN(a) ? b : a); + schedule.tween = tween1; }; } -function nogamma(a, b) { - var d = b - a; - return d ? linear$1(a, d) : constant$3(isNaN(a) ? b : a); -} - -var interpolateRgb = (function rgbGamma(y) { - var color$$1 = gamma(y); - - function rgb$$1(start, end) { - var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r), - g = color$$1(start.g, end.g), - b = color$$1(start.b, end.b), - opacity = color$$1(start.opacity, end.opacity); - return function(t) { - start.r = r(t); - start.g = g(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; - } - - rgb$$1.gamma = rgbGamma; - - return rgb$$1; -})(1); +function tweenFunction(id, name, value) { + var tween0, tween1; + if (typeof value !== "function") throw new Error; + return function() { + var schedule = set$1(this, id), + tween = schedule.tween; -function rgbSpline(spline) { - return function(colors) { - var n = colors.length, - r = new Array(n), - g = new Array(n), - b = new Array(n), - i, color$$1; - for (i = 0; i < n; ++i) { - color$$1 = rgb(colors[i]); - r[i] = color$$1.r || 0; - g[i] = color$$1.g || 0; - b[i] = color$$1.b || 0; + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) tween1.push(t); } - r = spline(r); - g = spline(g); - b = spline(b); - color$$1.opacity = 1; - return function(t) { - color$$1.r = r(t); - color$$1.g = g(t); - color$$1.b = b(t); - return color$$1 + ""; - }; + + schedule.tween = tween1; }; } -var rgbBasis = rgbSpline(basis$2); -var rgbBasisClosed = rgbSpline(basisClosed$1); +var transition_tween = function(name, value) { + var id = this._id; -var array$1 = function(a, b) { - var nb = b ? b.length : 0, - na = a ? Math.min(nb, a.length) : 0, - x = new Array(nb), - c = new Array(nb), - i; + name += ""; - for (i = 0; i < na; ++i) x[i] = interpolate(a[i], b[i]); - for (; i < nb; ++i) c[i] = b[i]; + if (arguments.length < 2) { + var tween = get$1(this.node(), id).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } - return function(t) { - for (i = 0; i < na; ++i) c[i] = x[i](t); - return c; - }; + return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); }; -var date = function(a, b) { - var d = new Date; - return a = +a, b -= a, function(t) { - return d.setTime(a + b * t), d; - }; -}; +function tweenValue(transition, name, value) { + var id = transition._id; -var interpolateNumber = function(a, b) { - return a = +a, b -= a, function(t) { - return a + b * t; - }; -}; + transition.each(function() { + var schedule = set$1(this, id); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); -var object = function(a, b) { - var i = {}, - c = {}, - k; + return function(node) { + return get$1(node, id).value[name]; + }; +} - if (a === null || typeof a !== "object") a = {}; - if (b === null || typeof b !== "object") b = {}; +var interpolate$$1 = function(a, b) { + var c; + return (typeof b === "number" ? reinterpolate + : b instanceof color ? interpolateRgb + : (c = color(b)) ? (b = c, interpolateRgb) + : interpolateString)(a, b); +}; - for (k in b) { - if (k in a) { - i[k] = interpolate(a[k], b[k]); - } else { - c[k] = b[k]; - } - } +function attrRemove$1(name) { + return function() { + this.removeAttribute(name); + }; +} - return function(t) { - for (k in i) c[k] = i[k](t); - return c; +function attrRemoveNS$1(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); }; -}; +} -var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; -var reB = new RegExp(reA.source, "g"); +function attrConstant$1(name, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} -function zero(b) { +function attrConstantNS$1(fullname, interpolate$$1, value1) { + var value00, + interpolate0; return function() { - return b; + var value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); }; } -function one(b) { - return function(t) { - return b(t) + ""; +function attrFunction$1(name, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttribute(name); + value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); }; } -var interpolateString = function(a, b) { - var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b - am, // current match in a - bm, // current match in b - bs, // string preceding current number in b, if any - i = -1, // index in s - s = [], // string constants and placeholders - q = []; // number interpolators +function attrFunctionNS$1(fullname, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); + value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} - // Coerce inputs to strings. - a = a + "", b = b + ""; +var transition_attr = function(name, value) { + var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$$1; + return this.attrTween(name, typeof value === "function" + ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) + : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) + : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value)); +}; - // Interpolate pairs of numbers in a & b. - while ((am = reA.exec(a)) - && (bm = reB.exec(b))) { - if ((bs = bm.index) > bi) { // a string precedes the next number in b - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match - if (s[i]) s[i] += bm; // coalesce with previous string - else s[++i] = bm; - } else { // interpolate non-matching numbers - s[++i] = null; - q.push({i: i, x: interpolateNumber(am, bm)}); - } - bi = reB.lastIndex; +function attrTweenNS(fullname, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttributeNS(fullname.space, fullname.local, i(t)); + }; } + tween._value = value; + return tween; +} - // Add remains of b. - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; +function attrTween(name, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttribute(name, i(t)); + }; } + tween._value = value; + return tween; +} - // Special optimization for only a single match. - // Otherwise, interpolate each of the numbers and rejoin the string. - return s.length < 2 ? (q[0] - ? one(q[0].x) - : zero(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 transition_attrTween = function(name, value) { + var key = "attr." + name; + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + var fullname = namespace(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); }; -var interpolate = function(a, b) { - var t = typeof b, c; - return b == null || t === "boolean" ? constant$3(b) - : (t === "number" ? interpolateNumber - : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString) - : b instanceof color ? interpolateRgb - : b instanceof Date ? date - : Array.isArray(b) ? array$1 - : isNaN(b) ? object - : interpolateNumber)(a, b); -}; +function delayFunction(id, value) { + return function() { + init(this, id).delay = +value.apply(this, arguments); + }; +} -var interpolateRound = function(a, b) { - return a = +a, b -= a, function(t) { - return Math.round(a + b * t); +function delayConstant(id, value) { + return value = +value, function() { + init(this, id).delay = value; }; -}; +} -var degrees = 180 / Math.PI; +var transition_delay = function(value) { + var id = this._id; -var identity$2 = { - translateX: 0, - translateY: 0, - rotate: 0, - skewX: 0, - scaleX: 1, - scaleY: 1 + return arguments.length + ? this.each((typeof value === "function" + ? delayFunction + : delayConstant)(id, value)) + : get$1(this.node(), id).delay; }; -var decompose = function(a, b, c, d, e, f) { - var scaleX, scaleY, skewX; - if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; - if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; - if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; - if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; - return { - translateX: e, - translateY: f, - rotate: Math.atan2(b, a) * degrees, - skewX: Math.atan(skewX) * degrees, - scaleX: scaleX, - scaleY: scaleY +function durationFunction(id, value) { + return function() { + set$1(this, id).duration = +value.apply(this, arguments); + }; +} + +function durationConstant(id, value) { + return value = +value, function() { + set$1(this, id).duration = value; }; +} + +var transition_duration = function(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? durationFunction + : durationConstant)(id, value)) + : get$1(this.node(), id).duration; }; -var cssNode; -var cssRoot; -var cssView; -var svgNode; - -function parseCss(value) { - if (value === "none") return identity$2; - if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; - cssNode.style.transform = value; - value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); - cssRoot.removeChild(cssNode); - value = value.slice(7, -1).split(","); - return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); +function easeConstant(id, value) { + if (typeof value !== "function") throw new Error; + return function() { + set$1(this, id).ease = value; + }; } -function parseSvg(value) { - if (value == null) return identity$2; - if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); - svgNode.setAttribute("transform", value); - if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2; - value = value.matrix; - return decompose(value.a, value.b, value.c, value.d, value.e, value.f); -} +var transition_ease = function(value) { + var id = this._id; -function interpolateTransform(parse, pxComma, pxParen, degParen) { + return arguments.length + ? this.each(easeConstant(id, value)) + : get$1(this.node(), id).ease; +}; - function pop(s) { - return s.length ? s.pop() + " " : ""; - } +var transition_filter = function(match) { + if (typeof match !== "function") match = matcher$1(match); - function translate(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push("translate(", null, pxComma, null, pxParen); - q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); - } else if (xb || yb) { - s.push("translate(" + xb + pxComma + yb + pxParen); + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } } } - function rotate(a, b, s, q) { - if (a !== b) { - if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path - q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)}); - } else if (b) { - s.push(pop(s) + "rotate(" + b + degParen); - } - } + return new Transition(subgroups, this._parents, this._name, this._id); +}; - function skewX(a, b, s, q) { - if (a !== b) { - q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)}); - } else if (b) { - s.push(pop(s) + "skewX(" + b + degParen); +var transition_merge = function(transition) { + if (transition._id !== this._id) throw new Error; + + for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } } } - function scale(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push(pop(s) + "scale(", null, ",", null, ")"); - q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); - } else if (xb !== 1 || yb !== 1) { - s.push(pop(s) + "scale(" + xb + "," + yb + ")"); - } + for (; j < m0; ++j) { + merges[j] = groups0[j]; } - return function(a, b) { - var s = [], // string constants and placeholders - q = []; // number interpolators - a = parse(a), b = parse(b); - translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); - rotate(a.rotate, b.rotate, s, q); - skewX(a.skewX, b.skewX, s, q); - scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); - a = b = null; // gc - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - }; + return new Transition(merges, this._parents, this._name, this._id); +}; + +function start(name) { + return (name + "").trim().split(/^|\s+/).every(function(t) { + var i = t.indexOf("."); + if (i >= 0) t = t.slice(0, i); + return !t || t === "start"; + }); } -var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); -var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); +function onFunction(id, name, listener) { + var on0, on1, sit = start(name) ? init : set$1; + return function() { + var schedule = sit(this, id), + on = schedule.on; -var rho = Math.SQRT2; -var rho2 = 2; -var rho4 = 4; -var epsilon2 = 1e-12; + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); -function cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; + schedule.on = on1; + }; } -function sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; -} +var transition_on = function(name, listener) { + var id = this._id; -function tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); + return arguments.length < 2 + ? get$1(this.node(), id).on.on(name) + : this.each(onFunction(id, name, listener)); +}; + +function removeFunction(id) { + return function() { + var parent = this.parentNode; + for (var i in this.__transition) if (+i !== id) return; + if (parent) parent.removeChild(this); + }; } -// p0 = [ux0, uy0, w0] -// p1 = [ux1, uy1, w1] -var 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; +var transition_remove = function() { + return this.on("end.remove", removeFunction(this._id)); +}; - // Special case for u0 ≅ u1. - if (d2 < epsilon2) { - S = Math.log(w1 / w0) / rho; - i = function(t) { - return [ - ux0 + t * dx, - uy0 + t * dy, - w0 * Math.exp(rho * t * S) - ]; - }; - } +var transition_select = function(select$$1) { + var name = this._name, + id = this._id; - // General case. - else { - var d1 = Math.sqrt(d2), - b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), - b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), - r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), - r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); - S = (r1 - r0) / rho; - i = function(t) { - var s = t * S, - coshr0 = cosh(r0), - u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); - return [ - ux0 + u * dx, - uy0 + u * dy, - w0 * coshr0 / cosh(rho * s + r0) - ]; - }; - } + if (typeof select$$1 !== "function") select$$1 = selector(select$$1); - i.duration = S * 1000; + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule(subgroup[i], name, id, i, subgroup, get$1(node, id)); + } + } + } - return i; + return new Transition(subgroups, this._parents, name, id); }; -function hsl$1(hue$$1) { - return function(start, end) { - var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h), - s = nogamma(start.s, end.s), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.s = s(t); - start.l = l(t); - start.opacity = opacity(t); - return start + ""; - }; - } -} - -var hsl$2 = hsl$1(hue); -var hslLong = hsl$1(nogamma); +var transition_selectAll = function(select$$1) { + var name = this._name, + id = this._id; -function lab$1(start, end) { - var l = nogamma((start = lab(start)).l, (end = lab(end)).l), - a = nogamma(start.a, end.a), - b = nogamma(start.b, end.b), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.l = l(t); - start.a = a(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; -} + if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1); -function hcl$1(hue$$1) { - return function(start, end) { - var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h), - c = nogamma(start.c, end.c), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.c = c(t); - start.l = l(t); - start.opacity = opacity(t); - return start + ""; - }; + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children = select$$1.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) { + if (child = children[k]) { + schedule(child, name, id, k, children, inherit); + } + } + subgroups.push(children); + parents.push(node); + } + } } -} -var hcl$2 = hcl$1(hue); -var hclLong = hcl$1(nogamma); + return new Transition(subgroups, parents, name, id); +}; + +var Selection$1 = selection.prototype.constructor; -function cubehelix$1(hue$$1) { - return (function cubehelixGamma(y) { - y = +y; +var transition_selection = function() { + return new Selection$1(this._groups, this._parents); +}; - function cubehelix$$1(start, end) { - var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h), - s = nogamma(start.s, end.s), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.s = s(t); - start.l = l(Math.pow(t, y)); - start.opacity = opacity(t); - return start + ""; - }; - } +function styleRemove$1(name, interpolate$$2) { + var value00, + value10, + interpolate0; + return function() { + var style = window(this).getComputedStyle(this, null), + value0 = style.getPropertyValue(name), + value1 = (this.style.removeProperty(name), style.getPropertyValue(name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$2(value00 = value0, value10 = value1); + }; +} - cubehelix$$1.gamma = cubehelixGamma; +function styleRemoveEnd(name) { + return function() { + this.style.removeProperty(name); + }; +} - return cubehelix$$1; - })(1); +function styleConstant$1(name, interpolate$$2, value1) { + var value00, + interpolate0; + return function() { + var value0 = window(this).getComputedStyle(this, null).getPropertyValue(name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$2(value00 = value0, value1); + }; } -var cubehelix$2 = cubehelix$1(hue); -var cubehelixLong = cubehelix$1(nogamma); +function styleFunction$1(name, interpolate$$2, value) { + var value00, + value10, + interpolate0; + return function() { + var style = window(this).getComputedStyle(this, null), + value0 = style.getPropertyValue(name), + value1 = value(this); + if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$2(value00 = value0, value10 = value1); + }; +} -var quantize = function(interpolator, n) { - var samples = new Array(n); - for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); - return samples; +var transition_style = function(name, value, priority) { + var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$$1; + return value == null ? this + .styleTween(name, styleRemove$1(name, i)) + .on("end.style." + name, styleRemoveEnd(name)) + : this.styleTween(name, typeof value === "function" + ? styleFunction$1(name, i, tweenValue(this, "style." + name, value)) + : styleConstant$1(name, i, value), priority); }; -var noop$1 = {value: function() {}}; - -function dispatch() { - for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { - if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); - _[t] = []; +function styleTween(name, value, priority) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.style.setProperty(name, i(t), priority); + }; } - return new Dispatch(_); + tween._value = value; + return tween; } -function Dispatch(_) { - this._ = _; +var transition_styleTween = function(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); +}; + +function textConstant$1(value) { + return function() { + this.textContent = value; + }; } -function parseTypenames(typenames, types) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); - return {type: t, name: name}; - }); +function textFunction$1(value) { + return function() { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; } -Dispatch.prototype = dispatch.prototype = { - constructor: Dispatch, - on: function(typename, callback) { - var _ = this._, - T = parseTypenames(typename + "", _), - t, - i = -1, - n = T.length; +var transition_text = function(value) { + return this.tween("text", typeof value === "function" + ? textFunction$1(tweenValue(this, "text", value)) + : textConstant$1(value == null ? "" : value + "")); +}; - // If no callback was specified, return the callback of the given type and name. - if (arguments.length < 2) { - while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; - return; - } +var transition_transition = function() { + var name = this._name, + id0 = this._id, + id1 = newId(); - // If a type was specified, set the callback for the given type and name. - // Otherwise, if a null callback was specified, remove callbacks of the given name. - if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); - while (++i < n) { - if (t = (typename = T[i]).type) _[t] = set$2(_[t], typename.name, callback); - else if (callback == null) for (t in _) _[t] = set$2(_[t], typename.name, null); + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit = get$1(node, id0); + schedule(node, name, id1, i, group, { + time: inherit.time + inherit.delay + inherit.duration, + delay: 0, + duration: inherit.duration, + ease: inherit.ease + }); + } } - - return this; - }, - copy: function() { - var copy = {}, _ = this._; - for (var t in _) copy[t] = _[t].slice(); - return new Dispatch(copy); - }, - call: function(type, that) { - if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - }, - apply: function(type, that, args) { - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); } + + return new Transition(groups, this._parents, name, id1); }; -function get(type, name) { - for (var i = 0, n = type.length, c; i < n; ++i) { - if ((c = type[i]).name === name) { - return c.value; - } - } -} +var id = 0; -function set$2(type, name, callback) { - for (var i = 0, n = type.length; i < n; ++i) { - if (type[i].name === name) { - type[i] = noop$1, type = type.slice(0, i).concat(type.slice(i + 1)); - break; - } - } - if (callback != null) type.push({name: name, value: callback}); - return type; +function Transition(groups, parents, name, id) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id; } -function objectConverter(columns) { - return new Function("d", "return {" + columns.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); +function transition(name) { + return selection().transition(name); } -function customConverter(columns, f) { - var object = objectConverter(columns); - return function(row, i) { - return f(object(row), i, columns); - }; +function newId() { + return ++id; } -// Compute unique columns in order of discovery. -function inferColumns(rows) { - var columnSet = Object.create(null), - columns = []; +var selection_prototype = selection.prototype; - rows.forEach(function(row) { - for (var column in row) { - if (!(column in columnSet)) { - columns.push(columnSet[column] = column); - } - } - }); +Transition.prototype = transition.prototype = { + constructor: Transition, + select: transition_select, + selectAll: transition_selectAll, + filter: transition_filter, + merge: transition_merge, + selection: transition_selection, + transition: transition_transition, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: transition_on, + attr: transition_attr, + attrTween: transition_attrTween, + style: transition_style, + styleTween: transition_styleTween, + text: transition_text, + remove: transition_remove, + tween: transition_tween, + delay: transition_delay, + duration: transition_duration, + ease: transition_ease +}; - return columns; +function linear$1(t) { + return +t; } -var dsv = function(delimiter) { - var reFormat = new RegExp("[\"" + delimiter + "\n]"), - delimiterCode = delimiter.charCodeAt(0); - - function parse(text, f) { - var convert, columns, rows = parseRows(text, function(row, i) { - if (convert) return convert(row, i - 1); - columns = row, convert = f ? customConverter(row, f) : objectConverter(row); - }); - rows.columns = columns; - return rows; - } - - function parseRows(text, f) { - var EOL = {}, // sentinel value for end-of-line - EOF = {}, // sentinel value for end-of-file - rows = [], // output rows - N = text.length, - I = 0, // current character index - n = 0, // the current line number - t, // the current token - eol; // is the current token followed by EOL? +function quadIn(t) { + return t * t; +} - function token() { - if (I >= N) return EOF; // special case: end of file - if (eol) return eol = false, EOL; // special case: end of line +function quadOut(t) { + return t * (2 - t); +} - // special case: quotes - var j = I, c; - 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; - 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, "\""); - } +function quadInOut(t) { + return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; +} - // common case: find next delimiter or newline - while (I < N) { - var k = 1; - c = text.charCodeAt(I++); - if (c === 10) eol = true; // \n - else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n - else if (c !== delimiterCode) continue; - return text.slice(j, I - k); - } +function cubicIn(t) { + return t * t * t; +} - // special case: last token before EOF - return text.slice(j); - } +function cubicOut(t) { + return --t * t * t + 1; +} - 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); - } +function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; +} - return rows; - } +var exponent = 3; - function format(rows, columns) { - if (columns == null) columns = inferColumns(rows); - return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { - return columns.map(function(column) { - return formatValue(row[column]); - }).join(delimiter); - })).join("\n"); - } +var polyIn = (function custom(e) { + e = +e; - function formatRows(rows) { - return rows.map(formatRow).join("\n"); + function polyIn(t) { + return Math.pow(t, e); } - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } + polyIn.exponent = custom; - function formatValue(text) { - return text == null ? "" - : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\"" - : text; + return polyIn; +})(exponent); + +var polyOut = (function custom(e) { + e = +e; + + function polyOut(t) { + return 1 - Math.pow(1 - t, e); } - return { - parse: parse, - parseRows: parseRows, - format: format, - formatRows: formatRows - }; -}; + polyOut.exponent = custom; -var csv = dsv(","); + return polyOut; +})(exponent); -var csvParse = csv.parse; -var csvParseRows = csv.parseRows; -var csvFormat = csv.format; -var csvFormatRows = csv.formatRows; +var polyInOut = (function custom(e) { + e = +e; -var tsv = dsv("\t"); + function polyInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; + } -var tsvParse = tsv.parse; -var tsvParseRows = tsv.parseRows; -var tsvFormat = tsv.format; -var tsvFormatRows = tsv.formatRows; + polyInOut.exponent = custom; -var request = function(url, callback) { - var request, - event = dispatch("beforesend", "progress", "load", "error"), - mimeType, - headers = map$1(), - xhr = new XMLHttpRequest, - user = null, - password = null, - response, - responseType, - timeout = 0; + return polyInOut; +})(exponent); - // If IE does not support CORS, use XDomainRequest. - if (typeof XDomainRequest !== "undefined" - && !("withCredentials" in xhr) - && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; +var pi = Math.PI; +var halfPi = pi / 2; - "onload" in xhr - ? xhr.onload = xhr.onerror = xhr.ontimeout = respond - : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; +function sinIn(t) { + return 1 - Math.cos(t * halfPi); +} - function respond(o) { - var status = xhr.status, result; - if (!status && hasResponse(xhr) - || status >= 200 && status < 300 - || status === 304) { - if (response) { - try { - result = response.call(request, xhr); - } catch (e) { - event.call("error", request, e); - return; - } - } else { - result = xhr; - } - event.call("load", request, result); - } else { - event.call("error", request, o); - } - } +function sinOut(t) { + return Math.sin(t * halfPi); +} - xhr.onprogress = function(e) { - event.call("progress", request, e); - }; +function sinInOut(t) { + return (1 - Math.cos(pi * t)) / 2; +} - request = { - header: function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers.get(name); - if (value == null) headers.remove(name); - else headers.set(name, value + ""); - return request; - }, +function expIn(t) { + return Math.pow(2, 10 * t - 10); +} - // If mimeType is non-null and no Accept header is set, a default is used. - mimeType: function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return request; - }, +function expOut(t) { + return 1 - Math.pow(2, -10 * t); +} - // Specifies what type the response value should take; - // for instance, arraybuffer, blob, document, or text. - responseType: function(value) { - if (!arguments.length) return responseType; - responseType = value; - return request; - }, +function expInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; +} - timeout: function(value) { - if (!arguments.length) return timeout; - timeout = +value; - return request; - }, +function circleIn(t) { + return 1 - Math.sqrt(1 - t * t); +} - user: function(value) { - return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); - }, +function circleOut(t) { + return Math.sqrt(1 - --t * t); +} - password: function(value) { - return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); - }, +function circleInOut(t) { + return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; +} - // Specify how to convert the response content to a specific type; - // changes the callback value on "load" events. - response: function(value) { - response = value; - return request; - }, +var b1 = 4 / 11; +var b2 = 6 / 11; +var b3 = 8 / 11; +var b4 = 3 / 4; +var b5 = 9 / 11; +var b6 = 10 / 11; +var b7 = 15 / 16; +var b8 = 21 / 22; +var b9 = 63 / 64; +var b0 = 1 / b1 / b1; - // Alias for send("GET", …). - get: function(data, callback) { - return request.send("GET", data, callback); - }, +function bounceIn(t) { + return 1 - bounceOut(1 - t); +} - // Alias for send("POST", …). - post: function(data, callback) { - return request.send("POST", data, callback); - }, +function bounceOut(t) { + return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; +} - // If callback is non-null, it will be used for error and load events. - send: function(method, data, callback) { - xhr.open(method, url, true, user, password); - if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); - if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); - if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); - if (responseType != null) xhr.responseType = responseType; - if (timeout > 0) xhr.timeout = timeout; - if (callback == null && typeof data === "function") callback = data, data = null; - if (callback != null && callback.length === 1) callback = fixCallback(callback); - if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); - event.call("beforesend", request, xhr); - xhr.send(data == null ? null : data); - return request; - }, +function bounceInOut(t) { + return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; +} - abort: function() { - xhr.abort(); - return request; - }, +var overshoot = 1.70158; - on: function() { - var value = event.on.apply(event, arguments); - return value === event ? request : value; - } - }; +var backIn = (function custom(s) { + s = +s; - if (callback != null) { - if (typeof callback !== "function") throw new Error("invalid callback: " + callback); - return request.get(callback); + function backIn(t) { + return t * t * ((s + 1) * t - s); } - return request; -}; + backIn.overshoot = custom; -function fixCallback(callback) { - return function(error, xhr) { - callback(error == null ? xhr : null); - }; -} + return backIn; +})(overshoot); -function hasResponse(xhr) { - var type = xhr.responseType; - return type && type !== "text" - ? xhr.response // null on error - : xhr.responseText; // "" on error -} +var backOut = (function custom(s) { + s = +s; -var type = function(defaultMimeType, response) { - return function(url, callback) { - var r = request(url).mimeType(defaultMimeType).response(response); - if (callback != null) { - if (typeof callback !== "function") throw new Error("invalid callback: " + callback); - return r.get(callback); - } - return r; - }; -}; + function backOut(t) { + return --t * t * ((s + 1) * t + s) + 1; + } -var html = type("text/html", function(xhr) { - return document.createRange().createContextualFragment(xhr.responseText); -}); + backOut.overshoot = custom; -var json = type("application/json", function(xhr) { - return JSON.parse(xhr.responseText); -}); + return backOut; +})(overshoot); -var text = type("text/plain", function(xhr) { - return xhr.responseText; -}); +var backInOut = (function custom(s) { + s = +s; -var xml = type("application/xml", function(xhr) { - var xml = xhr.responseXML; - if (!xml) throw new Error("parse error"); - return xml; -}); + function backInOut(t) { + return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; + } -var dsv$1 = function(defaultMimeType, parse) { - return function(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var r = request(url).mimeType(defaultMimeType); - r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; - r.row(row); - return callback ? r.get(callback) : r; - }; -}; + backInOut.overshoot = custom; -function responseOf(parse, row) { - return function(request$$1) { - return parse(request$$1.responseText, row); - }; -} + return backInOut; +})(overshoot); -var csv$1 = dsv$1("text/csv", csvParse); +var tau = 2 * Math.PI; +var amplitude = 1; +var period = 0.3; -var tsv$1 = dsv$1("text/tab-separated-values", tsvParse); +var elasticIn = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); -var frame = 0; -var timeout = 0; -var interval = 0; -var pokeDelay = 1000; -var taskHead; -var taskTail; -var clockLast = 0; -var clockNow = 0; -var clockSkew = 0; -var clock = typeof performance === "object" && performance.now ? performance : Date; -var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); }; + function elasticIn(t) { + return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); + } -function now() { - return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); -} + elasticIn.amplitude = function(a) { return custom(a, p * tau); }; + elasticIn.period = function(p) { return custom(a, p); }; -function clearNow() { - clockNow = 0; -} + return elasticIn; +})(amplitude, period); -function Timer() { - this._call = - this._time = - this._next = null; -} +var elasticOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); -Timer.prototype = timer.prototype = { - constructor: Timer, - restart: function(callback, delay, time) { - if (typeof callback !== "function") throw new TypeError("callback is not a function"); - time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); - if (!this._next && taskTail !== this) { - if (taskTail) taskTail._next = this; - else taskHead = this; - taskTail = this; - } - this._call = callback; - this._time = time; - sleep(); - }, - stop: function() { - if (this._call) { - this._call = null; - this._time = Infinity; - sleep(); - } + function elasticOut(t) { + return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); } -}; -function timer(callback, delay, time) { - var t = new Timer; - t.restart(callback, delay, time); - return t; -} + elasticOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticOut.period = function(p) { return custom(a, p); }; -function timerFlush() { - now(); // Get the current time, if not already set. - ++frame; // Pretend we’ve set an alarm, if we haven’t already. - var t = taskHead, e; - while (t) { - if ((e = clockNow - t._time) >= 0) t._call.call(null, e); - t = t._next; - } - --frame; -} + return elasticOut; +})(amplitude, period); -function wake() { - clockNow = (clockLast = clock.now()) + clockSkew; - frame = timeout = 0; - try { - timerFlush(); - } finally { - frame = 0; - nap(); - clockNow = 0; +var elasticInOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticInOut(t) { + return ((t = t * 2 - 1) < 0 + ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) + : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; } -} -function poke$1() { - var now = clock.now(), delay = now - clockLast; - if (delay > pokeDelay) clockSkew -= delay, clockLast = now; -} + elasticInOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticInOut.period = function(p) { return custom(a, p); }; -function nap() { - var t0, t1 = taskHead, t2, time = Infinity; - while (t1) { - if (t1._call) { - if (time > t1._time) time = t1._time; - t0 = t1, t1 = t1._next; - } else { - t2 = t1._next, t1._next = null; - t1 = t0 ? t0._next = t2 : taskHead = t2; + return elasticInOut; +})(amplitude, period); + +var defaultTiming = { + time: null, // Set on use. + delay: 0, + duration: 250, + ease: cubicInOut +}; + +function inherit(node, id) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id])) { + if (!(node = node.parentNode)) { + return defaultTiming.time = now(), defaultTiming; } } - taskTail = t0; - sleep(time); + return timing; } -function sleep(time) { - if (frame) return; // Soonest alarm already set, or will be. - if (timeout) timeout = clearTimeout(timeout); - var delay = time - clockNow; - if (delay > 24) { - if (time < Infinity) timeout = setTimeout(wake, delay); - if (interval) interval = clearInterval(interval); +var selection_transition = function(name) { + var id, + timing; + + if (name instanceof Transition) { + id = name._id, name = name._name; } else { - if (!interval) interval = setInterval(poke$1, pokeDelay); - frame = 1, setFrame(wake); + id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; + } + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule(node, name, id, i, group, timing || inherit(node, id)); + } + } } -} -var timeout$1 = function(callback, delay, time) { - var t = new Timer; - delay = delay == null ? 0 : +delay; - t.restart(function(elapsed) { - t.stop(); - callback(elapsed + delay); - }, delay, time); - return t; + return new Transition(groups, this._parents, name, id); }; -var interval$1 = function(callback, delay, time) { - var t = new Timer, total = delay; - if (delay == null) return t.restart(callback, delay, time), t; - delay = +delay, time = time == null ? now() : +time; - t.restart(function tick(elapsed) { - elapsed += total; - t.restart(tick, total += delay, time); - callback(elapsed); - }, delay, time); - return t; -}; +selection.prototype.interrupt = selection_interrupt; +selection.prototype.transition = selection_transition; -var t0$1 = new Date; -var t1$1 = new Date; +var root$1 = [null]; -function newInterval(floori, offseti, count, field) { +var active = function(node, name) { + var schedules = node.__transition, + schedule, + i; - function interval(date) { - return floori(date = new Date(+date)), date; + if (schedules) { + name = name == null ? null : name + ""; + for (i in schedules) { + if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { + return new Transition([[node]], root$1, name, +i); + } + } } - interval.floor = interval; - - interval.ceil = function(date) { - return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; - }; + return null; +}; - interval.round = function(date) { - var d0 = interval(date), - d1 = interval.ceil(date); - return date - d0 < d1 - date ? d0 : d1; +var constant$4 = function(x) { + return function() { + return x; }; +}; - interval.offset = function(date, step) { - return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; - }; +var BrushEvent = function(target, type, selection) { + this.target = target; + this.type = type; + this.selection = selection; +}; - interval.range = function(start, stop, step) { - var range = []; - start = interval.ceil(start); - step = step == null ? 1 : Math.floor(step); - if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date - do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) - return range; - }; +function nopropagation$1() { + exports.event.stopImmediatePropagation(); +} - interval.filter = function(test) { - return newInterval(function(date) { - if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); - }, function(date, step) { - if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty - }); - }; +var noevent$1 = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); +}; - if (count) { - interval.count = function(start, end) { - t0$1.setTime(+start), t1$1.setTime(+end); - floori(t0$1), floori(t1$1); - return Math.floor(count(t0$1, t1$1)); - }; +var MODE_DRAG = {name: "drag"}; +var MODE_SPACE = {name: "space"}; +var MODE_HANDLE = {name: "handle"}; +var MODE_CENTER = {name: "center"}; - interval.every = function(step) { - step = Math.floor(step); - return !isFinite(step) || !(step > 0) ? null - : !(step > 1) ? interval - : interval.filter(field - ? function(d) { return field(d) % step === 0; } - : function(d) { return interval.count(0, d) % step === 0; }); - }; - } +var X = { + name: "x", + handles: ["e", "w"].map(type), + input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; }, + output: function(xy) { return xy && [xy[0][0], xy[1][0]]; } +}; - return interval; -} +var Y = { + name: "y", + handles: ["n", "s"].map(type), + input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; }, + output: function(xy) { return xy && [xy[0][1], xy[1][1]]; } +}; -var millisecond = newInterval(function() { - // noop -}, function(date, step) { - date.setTime(+date + step); -}, function(start, end) { - return end - start; -}); +var XY = { + name: "xy", + handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type), + input: function(xy) { return xy; }, + output: function(xy) { return xy; } +}; -// An optimized implementation for this simple case. -millisecond.every = function(k) { - k = Math.floor(k); - if (!isFinite(k) || !(k > 0)) return null; - if (!(k > 1)) return millisecond; - return newInterval(function(date) { - date.setTime(Math.floor(date / k) * k); - }, function(date, step) { - date.setTime(+date + step * k); - }, function(start, end) { - return (end - start) / k; - }); +var cursors = { + overlay: "crosshair", + selection: "move", + 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 milliseconds = millisecond.range; +var flipX = { + e: "w", + w: "e", + nw: "ne", + ne: "nw", + se: "sw", + sw: "se" +}; -var durationSecond = 1e3; -var durationMinute = 6e4; -var durationHour = 36e5; -var durationDay = 864e5; -var durationWeek = 6048e5; +var flipY = { + n: "s", + s: "n", + nw: "sw", + ne: "se", + se: "ne", + sw: "nw" +}; -var second = newInterval(function(date) { - date.setTime(Math.floor(date / durationSecond) * durationSecond); -}, function(date, step) { - date.setTime(+date + step * durationSecond); -}, function(start, end) { - return (end - start) / durationSecond; -}, function(date) { - return date.getUTCSeconds(); -}); +var signsX = { + overlay: +1, + selection: +1, + n: null, + e: +1, + s: null, + w: -1, + nw: -1, + ne: +1, + se: +1, + sw: -1 +}; -var seconds = second.range; +var signsY = { + overlay: +1, + selection: +1, + n: -1, + e: null, + s: +1, + w: null, + nw: -1, + ne: -1, + se: +1, + sw: +1 +}; -var minute = newInterval(function(date) { - date.setTime(Math.floor(date / durationMinute) * durationMinute); -}, function(date, step) { - date.setTime(+date + step * durationMinute); -}, function(start, end) { - return (end - start) / durationMinute; -}, function(date) { - return date.getMinutes(); -}); +function type(t) { + return {type: t}; +} -var minutes = minute.range; +// Ignore right-click, since that should open the context menu. +function defaultFilter() { + return !exports.event.button; +} -var hour = newInterval(function(date) { - var offset = date.getTimezoneOffset() * durationMinute % durationHour; - if (offset < 0) offset += durationHour; - date.setTime(Math.floor((+date - offset) / durationHour) * durationHour + offset); -}, function(date, step) { - date.setTime(+date + step * durationHour); -}, function(start, end) { - return (end - start) / durationHour; -}, function(date) { - return date.getHours(); -}); +function defaultExtent() { + var svg = this.ownerSVGElement || this; + return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; +} -var hours = hour.range; +// Like d3.local, but with the name “__brush” rather than auto-generated. +function local$$1(node) { + while (!node.__brush) if (!(node = node.parentNode)) return; + return node.__brush; +} -var day = newInterval(function(date) { - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setDate(date.getDate() + step); -}, function(start, end) { - return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay; -}, function(date) { - return date.getDate() - 1; -}); +function empty(extent) { + return extent[0][0] === extent[1][0] + || extent[0][1] === extent[1][1]; +} -var days = day.range; +function brushSelection(node) { + var state = node.__brush; + return state ? state.dim.output(state.selection) : null; +} -function weekday(i) { - return newInterval(function(date) { - date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); - date.setHours(0, 0, 0, 0); - }, function(date, step) { - date.setDate(date.getDate() + step * 7); - }, function(start, end) { - return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek; - }); +function brushX() { + return brush$1(X); } -var sunday = weekday(0); -var monday = weekday(1); -var tuesday = weekday(2); -var wednesday = weekday(3); -var thursday = weekday(4); -var friday = weekday(5); -var saturday = weekday(6); +function brushY() { + return brush$1(Y); +} -var sundays = sunday.range; -var mondays = monday.range; -var tuesdays = tuesday.range; -var wednesdays = wednesday.range; -var thursdays = thursday.range; -var fridays = friday.range; -var saturdays = saturday.range; +var brush = function() { + return brush$1(XY); +}; -var month = newInterval(function(date) { - date.setDate(1); - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setMonth(date.getMonth() + step); -}, function(start, end) { - return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; -}, function(date) { - return date.getMonth(); -}); +function brush$1(dim) { + var extent = defaultExtent, + filter = defaultFilter, + listeners = dispatch(brush, "start", "brush", "end"), + handleSize = 6, + touchending; -var months = month.range; + function brush(group) { + var overlay = group + .property("__brush", initialize) + .selectAll(".overlay") + .data([type("overlay")]); -var year = newInterval(function(date) { - date.setMonth(0, 1); - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setFullYear(date.getFullYear() + step); -}, function(start, end) { - return end.getFullYear() - start.getFullYear(); -}, function(date) { - return date.getFullYear(); -}); + overlay.enter().append("rect") + .attr("class", "overlay") + .attr("pointer-events", "all") + .attr("cursor", cursors.overlay) + .merge(overlay) + .each(function() { + var extent = local$$1(this).extent; + select(this) + .attr("x", extent[0][0]) + .attr("y", extent[0][1]) + .attr("width", extent[1][0] - extent[0][0]) + .attr("height", extent[1][1] - extent[0][1]); + }); -// An optimized implementation for this simple case. -year.every = function(k) { - return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { - date.setFullYear(Math.floor(date.getFullYear() / k) * k); - date.setMonth(0, 1); - date.setHours(0, 0, 0, 0); - }, function(date, step) { - date.setFullYear(date.getFullYear() + step * k); - }); -}; + group.selectAll(".selection") + .data([type("selection")]) + .enter().append("rect") + .attr("class", "selection") + .attr("cursor", cursors.selection) + .attr("fill", "#777") + .attr("fill-opacity", 0.3) + .attr("stroke", "#fff") + .attr("shape-rendering", "crispEdges"); -var years = year.range; + var handle = group.selectAll(".handle") + .data(dim.handles, function(d) { return d.type; }); -var utcMinute = newInterval(function(date) { - date.setUTCSeconds(0, 0); -}, function(date, step) { - date.setTime(+date + step * durationMinute); -}, function(start, end) { - return (end - start) / durationMinute; -}, function(date) { - return date.getUTCMinutes(); -}); + handle.exit().remove(); -var utcMinutes = utcMinute.range; + handle.enter().append("rect") + .attr("class", function(d) { return "handle handle--" + d.type; }) + .attr("cursor", function(d) { return cursors[d.type]; }); -var utcHour = newInterval(function(date) { - date.setUTCMinutes(0, 0, 0); -}, function(date, step) { - date.setTime(+date + step * durationHour); -}, function(start, end) { - return (end - start) / durationHour; -}, function(date) { - return date.getUTCHours(); -}); + group + .each(redraw) + .attr("fill", "none") + .attr("pointer-events", "all") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") + .on("mousedown.brush touchstart.brush", started); + } -var utcHours = utcHour.range; + brush.move = function(group, selection$$1) { + if (group.selection) { + group + .on("start.brush", function() { emitter(this, arguments).beforestart().start(); }) + .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); }) + .tween("brush", function() { + var that = this, + state = that.__brush, + emit = emitter(that, arguments), + selection0 = state.selection, + selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent), + i = interpolateValue(selection0, selection1); -var utcDay = newInterval(function(date) { - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCDate(date.getUTCDate() + step); -}, function(start, end) { - return (end - start) / durationDay; -}, function(date) { - return date.getUTCDate() - 1; -}); + function tween(t) { + state.selection = t === 1 && empty(selection1) ? null : i(t); + redraw.call(that); + emit.brush(); + } -var utcDays = utcDay.range; + return selection0 && selection1 ? tween : tween(1); + }); + } else { + group + .each(function() { + var that = this, + args = arguments, + state = that.__brush, + selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent), + emit = emitter(that, args).beforestart(); -function utcWeekday(i) { - return newInterval(function(date) { - date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); - date.setUTCHours(0, 0, 0, 0); - }, function(date, step) { - date.setUTCDate(date.getUTCDate() + step * 7); - }, function(start, end) { - return (end - start) / durationWeek; - }); -} + interrupt(that); + state.selection = selection1 == null || empty(selection1) ? null : selection1; + redraw.call(that); + emit.start().brush().end(); + }); + } + }; -var utcSunday = utcWeekday(0); -var utcMonday = utcWeekday(1); -var utcTuesday = utcWeekday(2); -var utcWednesday = utcWeekday(3); -var utcThursday = utcWeekday(4); -var utcFriday = utcWeekday(5); -var utcSaturday = utcWeekday(6); + function redraw() { + var group = select(this), + selection$$1 = local$$1(this).selection; -var utcSundays = utcSunday.range; -var utcMondays = utcMonday.range; -var utcTuesdays = utcTuesday.range; -var utcWednesdays = utcWednesday.range; -var utcThursdays = utcThursday.range; -var utcFridays = utcFriday.range; -var utcSaturdays = utcSaturday.range; + if (selection$$1) { + group.selectAll(".selection") + .style("display", null) + .attr("x", selection$$1[0][0]) + .attr("y", selection$$1[0][1]) + .attr("width", selection$$1[1][0] - selection$$1[0][0]) + .attr("height", selection$$1[1][1] - selection$$1[0][1]); -var utcMonth = newInterval(function(date) { - date.setUTCDate(1); - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCMonth(date.getUTCMonth() + step); -}, function(start, end) { - return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; -}, function(date) { - return date.getUTCMonth(); -}); + group.selectAll(".handle") + .style("display", null) + .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; }) + .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; }) + .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; }) + .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; }); + } -var utcMonths = utcMonth.range; + else { + group.selectAll(".selection,.handle") + .style("display", "none") + .attr("x", null) + .attr("y", null) + .attr("width", null) + .attr("height", null); + } + } -var utcYear = newInterval(function(date) { - date.setUTCMonth(0, 1); - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCFullYear(date.getUTCFullYear() + step); -}, function(start, end) { - return end.getUTCFullYear() - start.getUTCFullYear(); -}, function(date) { - return date.getUTCFullYear(); -}); + function emitter(that, args) { + return that.__brush.emitter || new Emitter(that, args); + } -// An optimized implementation for this simple case. -utcYear.every = function(k) { - return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { - date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); - date.setUTCMonth(0, 1); - date.setUTCHours(0, 0, 0, 0); - }, function(date, step) { - date.setUTCFullYear(date.getUTCFullYear() + step * k); - }); -}; + function Emitter(that, args) { + this.that = that; + this.args = args; + this.state = that.__brush; + this.active = 0; + } + + Emitter.prototype = { + beforestart: function() { + if (++this.active === 1) this.state.emitter = this, this.starting = true; + return this; + }, + start: function() { + if (this.starting) this.starting = false, this.emit("start"); + return this; + }, + brush: function() { + this.emit("brush"); + return this; + }, + end: function() { + if (--this.active === 0) delete this.state.emitter, this.emit("end"); + return this; + }, + emit: function(type) { + customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); + } + }; -var utcYears = utcYear.range; + function started() { + if (exports.event.touches) { if (exports.event.changedTouches.length < exports.event.touches.length) return noevent$1(); } + else if (touchending) return; + if (!filter.apply(this, arguments)) return; -// Computes the decimal coefficient and exponent of the specified number x with -// significant digits p, where x is positive and p is in [1, 21] or undefined. -// For example, formatDecimal(1.23) returns ["123", 0]. -var formatDecimal = function(x, p) { - if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity - var i, coefficient = x.slice(0, i); + var that = this, + type = exports.event.target.__data__.type, + mode = (exports.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (exports.event.altKey ? MODE_CENTER : MODE_HANDLE), + signX = dim === Y ? null : signsX[type], + signY = dim === X ? null : signsY[type], + state = local$$1(that), + extent = state.extent, + selection$$1 = state.selection, + W = extent[0][0], w0, w1, + N = extent[0][1], n0, n1, + E = extent[1][0], e0, e1, + S = extent[1][1], s0, s1, + dx, + dy, + moving, + shifting = signX && signY && exports.event.shiftKey, + lockX, + lockY, + point0 = mouse(that), + point = point0, + emit = emitter(that, arguments).beforestart(); - // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ - // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). - return [ - coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, - +x.slice(i + 1) - ]; -}; + if (type === "overlay") { + state.selection = selection$$1 = [ + [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], + [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] + ]; + } else { + w0 = selection$$1[0][0]; + n0 = selection$$1[0][1]; + e0 = selection$$1[1][0]; + s0 = selection$$1[1][1]; + } -var exponent$1 = function(x) { - return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; -}; + w1 = w0; + n1 = n0; + e1 = e0; + s1 = s0; -var formatGroup = function(grouping, thousands) { - return function(value, width) { - var i = value.length, - t = [], - j = 0, - g = grouping[0], - length = 0; + var group = select(that) + .attr("pointer-events", "none"); - 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 = grouping[j = (j + 1) % grouping.length]; - } + var overlay = group.selectAll(".overlay") + .attr("cursor", cursors[type]); - return t.reverse().join(thousands); - }; -}; + if (exports.event.touches) { + group + .on("touchmove.brush", moved, true) + .on("touchend.brush touchcancel.brush", ended, true); + } else { + var view = select(exports.event.view) + .on("keydown.brush", keydowned, true) + .on("keyup.brush", keyupped, true) + .on("mousemove.brush", moved, true) + .on("mouseup.brush", ended, true); -var formatDefault = function(x, p) { - x = x.toPrecision(p); + dragDisable(exports.event.view); + } - out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { - switch (x[i]) { - case ".": i0 = i1 = i; break; - case "0": if (i0 === 0) i0 = i; i1 = i; break; - case "e": break out; - default: if (i0 > 0) i0 = 0; break; + nopropagation$1(); + interrupt(that); + redraw.call(that); + emit.start(); + + function moved() { + var point1 = mouse(that); + if (shifting && !lockX && !lockY) { + if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true; + else lockX = true; + } + point = point1; + moving = true; + noevent$1(); + move(); } - } - return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; -}; + function move() { + var t; -var prefixExponent; + dx = point[0] - point0[0]; + dy = point[1] - point0[1]; -var formatPrefixAuto = function(x, p) { - var d = formatDecimal(x, p); - if (!d) return x + ""; - var coefficient = d[0], - exponent = d[1], - i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, - n = coefficient.length; - return i === n ? coefficient - : i > n ? coefficient + new Array(i - n + 1).join("0") - : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) - : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! -}; + switch (mode) { + case MODE_SPACE: + case MODE_DRAG: { + if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; + if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; + break; + } + case MODE_HANDLE: { + if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; + else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; + if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; + else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; + break; + } + case MODE_CENTER: { + if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); + if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); + break; + } + } -var formatRounded = function(x, p) { - var d = formatDecimal(x, p); - if (!d) return x + ""; - var coefficient = d[0], - exponent = d[1]; - return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient - : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) - : coefficient + new Array(exponent - coefficient.length + 2).join("0"); -}; + if (e1 < w1) { + signX *= -1; + t = w0, w0 = e0, e0 = t; + t = w1, w1 = e1, e1 = t; + if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]); + } -var formatTypes = { - "": formatDefault, - "%": function(x, p) { return (x * 100).toFixed(p); }, - "b": function(x) { return Math.round(x).toString(2); }, - "c": function(x) { return x + ""; }, - "d": function(x) { return Math.round(x).toString(10); }, - "e": function(x, p) { return x.toExponential(p); }, - "f": function(x, p) { return x.toFixed(p); }, - "g": function(x, p) { return x.toPrecision(p); }, - "o": function(x) { return Math.round(x).toString(8); }, - "p": function(x, p) { return formatRounded(x * 100, p); }, - "r": formatRounded, - "s": formatPrefixAuto, - "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, - "x": function(x) { return Math.round(x).toString(16); } -}; + if (s1 < n1) { + signY *= -1; + t = n0, n0 = s0, s0 = t; + t = n1, n1 = s1, s1 = t; + if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]); + } -// [[fill]align][sign][symbol][0][width][,][.precision][type] -var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; + if (state.selection) selection$$1 = state.selection; // May be set by brush.move! + if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0]; + if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1]; -var formatSpecifier = function(specifier) { - return new FormatSpecifier(specifier); -}; + if (selection$$1[0][0] !== w1 + || selection$$1[0][1] !== n1 + || selection$$1[1][0] !== e1 + || selection$$1[1][1] !== s1) { + state.selection = [[w1, n1], [e1, s1]]; + redraw.call(that); + emit.brush(); + } + } -function FormatSpecifier(specifier) { - if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); + function ended() { + nopropagation$1(); + if (exports.event.touches) { + if (exports.event.touches.length) return; + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + group.on("touchmove.brush touchend.brush touchcancel.brush", null); + } else { + yesdrag(exports.event.view, moving); + view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); + } + group.attr("pointer-events", "all"); + overlay.attr("cursor", cursors.overlay); + if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)! + if (empty(selection$$1)) state.selection = null, redraw.call(that); + emit.end(); + } - var match, - fill = match[1] || " ", - align = match[2] || ">", - sign = match[3] || "-", - symbol = match[4] || "", - zero = !!match[5], - width = match[6] && +match[6], - comma = !!match[7], - precision = match[8] && +match[8].slice(1), - type = match[9] || ""; + function keydowned() { + switch (exports.event.keyCode) { + case 16: { // SHIFT + shifting = signX && signY; + break; + } + case 18: { // ALT + if (mode === MODE_HANDLE) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + move(); + } + break; + } + case 32: { // SPACE; takes priority over ALT + if (mode === MODE_HANDLE || mode === MODE_CENTER) { + if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx; + if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy; + mode = MODE_SPACE; + overlay.attr("cursor", cursors.selection); + move(); + } + break; + } + default: return; + } + noevent$1(); + } - // The "n" type is an alias for ",g". - if (type === "n") comma = true, type = "g"; + function keyupped() { + switch (exports.event.keyCode) { + case 16: { // SHIFT + if (shifting) { + lockX = lockY = shifting = false; + move(); + } + break; + } + case 18: { // ALT + if (mode === MODE_CENTER) { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + move(); + } + break; + } + case 32: { // SPACE + if (mode === MODE_SPACE) { + if (exports.event.altKey) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + } else { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + } + overlay.attr("cursor", cursors[type]); + move(); + } + break; + } + default: return; + } + noevent$1(); + } + } - // Map invalid types to the default format. - else if (!formatTypes[type]) type = ""; + function initialize() { + var state = this.__brush || {selection: null}; + state.extent = extent.apply(this, arguments); + state.dim = dim; + return state; + } - // If zero fill is specified, padding goes after sign and before digits. - if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; + brush.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent; + }; - this.fill = fill; - this.align = align; - this.sign = sign; - this.symbol = symbol; - this.zero = zero; - this.width = width; - this.comma = comma; - this.precision = precision; - this.type = type; -} + brush.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter; + }; -FormatSpecifier.prototype.toString = function() { - return this.fill - + this.align - + this.sign - + this.symbol - + (this.zero ? "0" : "") - + (this.width == null ? "" : Math.max(1, this.width | 0)) - + (this.comma ? "," : "") - + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) - + this.type; -}; + brush.handleSize = function(_) { + return arguments.length ? (handleSize = +_, brush) : handleSize; + }; -var prefixes = ["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"]; + brush.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? brush : value; + }; -function identity$3(x) { - return x; + return brush; } -var formatLocale = function(locale) { - var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3, - currency = locale.currency, - decimal = locale.decimal; - - function newFormat(specifier) { - specifier = formatSpecifier(specifier); - - var fill = specifier.fill, - align = specifier.align, - sign = specifier.sign, - symbol = specifier.symbol, - zero = specifier.zero, - width = specifier.width, - comma = specifier.comma, - precision = specifier.precision, - type = specifier.type; - - // Compute the prefix and suffix. - // For SI-prefix, the suffix is lazily computed. - var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", - suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : ""; - - // What format function should we use? - // Is this an integer type? - // Can this type generate exponential notation? - var formatType = formatTypes[type], - maybeSuffix = !type || /[defgprs%]/.test(type); +var cos = Math.cos; +var sin = Math.sin; +var pi$1 = Math.PI; +var halfPi$1 = pi$1 / 2; +var tau$1 = pi$1 * 2; +var max$1 = Math.max; - // Set the default precision if not specified, - // or clamp the specified precision to the supported range. - // For significant precision, it must be in [1, 21]. - // For fixed precision, it must be in [0, 20]. - precision = precision == null ? (type ? 6 : 12) - : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) - : Math.max(0, Math.min(20, precision)); +function compareValue(compare) { + return function(a, b) { + return compare( + a.source.value + a.target.value, + b.source.value + b.target.value + ); + }; +} - function format(value) { - var valuePrefix = prefix, - valueSuffix = suffix, - i, n, c; +var chord = function() { + var padAngle = 0, + sortGroups = null, + sortSubgroups = null, + sortChords = null; - if (type === "c") { - valueSuffix = formatType(value) + valueSuffix; - value = ""; - } else { - value = +value; + function chord(matrix) { + var n = matrix.length, + groupSums = [], + groupIndex = sequence(n), + subgroupIndex = [], + chords = [], + groups = chords.groups = new Array(n), + subgroups = new Array(n * n), + k, + x, + x0, + dx, + i, + j; - // Convert negative to positive, and compute the prefix. - // Note that -0 is not less than 0, but 1 / -0 is! - var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true); + // Compute the sum. + k = 0, i = -1; while (++i < n) { + x = 0, j = -1; while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(sequence(n)); + k += x; + } - // Perform the initial formatting. - value = formatType(value, precision); + // Sort groups… + if (sortGroups) groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); - // If the original value was negative, it may be rounded to zero during - // formatting; treat this as (positive) zero. - if (valueNegative) { - i = -1, n = value.length; - valueNegative = false; - while (++i < n) { - if (c = value.charCodeAt(i), (48 < c && c < 58) - || (type === "x" && 96 < c && c < 103) - || (type === "X" && 64 < c && c < 71)) { - valueNegative = true; - break; - } - } - } + // Sort subgroups… + if (sortSubgroups) subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); - // Compute the prefix and suffix. - valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; - valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); + // Convert the sum to scaling factor for [0, 2pi]. + // TODO Allow start and end angle to be specified? + // TODO Allow padding to be specified as percentage? + k = max$1(0, tau$1 - padAngle * n) / k; + dx = k ? padAngle : tau$1 / n; - // Break the formatted value into the integer “value” part that can be - // grouped, and fractional or exponential “suffix” part that is not. - if (maybeSuffix) { - i = -1, n = value.length; - while (++i < n) { - if (c = value.charCodeAt(i), 48 > c || c > 57) { - valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; - value = value.slice(0, i); - break; - } - } - } + // Compute the start and end angle for each group and subgroup. + // Note: Opera has a bug reordering object literal properties! + 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[dj * n + di] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += dx; + } - // If the fill character is not "0", grouping is applied before padding. - if (comma && !zero) value = group(value, Infinity); - - // Compute the padding. - var length = valuePrefix.length + value.length + valueSuffix.length, - padding = length < width ? new Array(width - length + 1).join(fill) : ""; - - // If the fill character is "0", grouping is applied after padding. - if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; - - // Reconstruct the final output based on the desired alignment. - switch (align) { - case "<": return valuePrefix + value + valueSuffix + padding; - case "=": return valuePrefix + padding + value + valueSuffix; - case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); + // Generate chords for each (non-empty) subgroup-subgroup link. + i = -1; while (++i < n) { + j = i - 1; while (++j < n) { + var source = subgroups[j * n + i], + target = subgroups[i * n + j]; + if (source.value || target.value) { + chords.push(source.value < target.value + ? {source: target, target: source} + : {source: source, target: target}); + } } - return padding + valuePrefix + value + valueSuffix; } - format.toString = function() { - return specifier + ""; - }; - - return format; - } - - function formatPrefix(specifier, value) { - var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), - e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3, - k = Math.pow(10, -e), - prefix = prefixes[8 + e / 3]; - return function(value) { - return f(k * value) + prefix; - }; + return sortChords ? chords.sort(sortChords) : chords; } - return { - format: newFormat, - formatPrefix: formatPrefix + chord.padAngle = function(_) { + return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle; }; -}; - -var locale$1; - + chord.sortGroups = function(_) { + return arguments.length ? (sortGroups = _, chord) : sortGroups; + }; -defaultLocale({ - decimal: ".", - thousands: ",", - grouping: [3], - currency: ["$", ""] -}); + chord.sortSubgroups = function(_) { + return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; + }; -function defaultLocale(definition) { - locale$1 = formatLocale(definition); - exports.format = locale$1.format; - exports.formatPrefix = locale$1.formatPrefix; - return locale$1; -} + chord.sortChords = function(_) { + return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; + }; -var precisionFixed = function(step) { - return Math.max(0, -exponent$1(Math.abs(step))); + return chord; }; -var precisionPrefix = function(step, value) { - return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step))); -}; +var slice$2 = Array.prototype.slice; -var precisionRound = function(step, max) { - step = Math.abs(step), max = Math.abs(max) - step; - return Math.max(0, exponent$1(max) - exponent$1(step)) + 1; +var constant$5 = function(x) { + return function() { + return x; + }; }; -function localDate(d) { - if (0 <= d.y && d.y < 100) { - var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); - date.setFullYear(d.y); - return date; - } - return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); -} +var pi$2 = Math.PI; +var tau$2 = 2 * pi$2; +var epsilon$1 = 1e-6; +var tauEpsilon = tau$2 - epsilon$1; -function utcDate(d) { - if (0 <= d.y && d.y < 100) { - var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); - date.setUTCFullYear(d.y); - return date; - } - return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); +function Path() { + this._x0 = this._y0 = // start of current subpath + this._x1 = this._y1 = null; // end of current subpath + this._ = ""; } -function newYear(y) { - return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; +function path() { + return new Path; } -function formatLocale$1(locale) { - var locale_dateTime = locale.dateTime, - locale_date = locale.date, - locale_time = locale.time, - locale_periods = locale.periods, - locale_weekdays = locale.days, - locale_shortWeekdays = locale.shortDays, - locale_months = locale.months, - locale_shortMonths = locale.shortMonths; +Path.prototype = path.prototype = { + constructor: Path, + moveTo: function(x, y) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); + }, + closePath: function() { + if (this._x1 !== null) { + this._x1 = this._x0, this._y1 = this._y0; + this._ += "Z"; + } + }, + lineTo: function(x, y) { + this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); + }, + quadraticCurveTo: function(x1, y1, x, y) { + this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { + this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + arcTo: function(x1, y1, x2, y2, r) { + x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; + var x0 = this._x1, + y0 = this._y1, + x21 = x2 - x1, + y21 = y2 - y1, + x01 = x0 - x1, + y01 = y0 - y1, + l01_2 = x01 * x01 + y01 * y01; - var periodRe = formatRe(locale_periods), - periodLookup = formatLookup(locale_periods), - weekdayRe = formatRe(locale_weekdays), - weekdayLookup = formatLookup(locale_weekdays), - shortWeekdayRe = formatRe(locale_shortWeekdays), - shortWeekdayLookup = formatLookup(locale_shortWeekdays), - monthRe = formatRe(locale_months), - monthLookup = formatLookup(locale_months), - shortMonthRe = formatRe(locale_shortMonths), - shortMonthLookup = formatLookup(locale_shortMonths); + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); - var formats = { - "a": formatShortWeekday, - "A": formatWeekday, - "b": formatShortMonth, - "B": formatMonth, - "c": null, - "d": formatDayOfMonth, - "e": formatDayOfMonth, - "H": formatHour24, - "I": formatHour12, - "j": formatDayOfYear, - "L": formatMilliseconds, - "m": formatMonthNumber, - "M": formatMinutes, - "p": formatPeriod, - "S": formatSeconds, - "U": formatWeekNumberSunday, - "w": formatWeekdayNumber, - "W": formatWeekNumberMonday, - "x": null, - "X": null, - "y": formatYear, - "Y": formatFullYear, - "Z": formatZone, - "%": formatLiteralPercent - }; + // Is this path empty? Move to (x1,y1). + if (this._x1 === null) { + this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); + } - var utcFormats = { - "a": formatUTCShortWeekday, - "A": formatUTCWeekday, - "b": formatUTCShortMonth, - "B": formatUTCMonth, - "c": null, - "d": formatUTCDayOfMonth, - "e": formatUTCDayOfMonth, - "H": formatUTCHour24, - "I": formatUTCHour12, - "j": formatUTCDayOfYear, - "L": formatUTCMilliseconds, - "m": formatUTCMonthNumber, - "M": formatUTCMinutes, - "p": formatUTCPeriod, - "S": formatUTCSeconds, - "U": formatUTCWeekNumberSunday, - "w": formatUTCWeekdayNumber, - "W": formatUTCWeekNumberMonday, - "x": null, - "X": null, - "y": formatUTCYear, - "Y": formatUTCFullYear, - "Z": formatUTCZone, - "%": formatLiteralPercent - }; + // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. + else if (!(l01_2 > epsilon$1)) {} - var parses = { - "a": parseShortWeekday, - "A": parseWeekday, - "b": parseShortMonth, - "B": parseMonth, - "c": parseLocaleDateTime, - "d": parseDayOfMonth, - "e": parseDayOfMonth, - "H": parseHour24, - "I": parseHour24, - "j": parseDayOfYear, - "L": parseMilliseconds, - "m": parseMonthNumber, - "M": parseMinutes, - "p": parsePeriod, - "S": parseSeconds, - "U": parseWeekNumberSunday, - "w": parseWeekdayNumber, - "W": parseWeekNumberMonday, - "x": parseLocaleDate, - "X": parseLocaleTime, - "y": parseYear, - "Y": parseFullYear, - "Z": parseZone, - "%": parseLiteralPercent - }; + // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? + // Equivalently, is (x1,y1) coincident with (x2,y2)? + // Or, is the radius zero? Line to (x1,y1). + else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) { + this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); + } + + // Otherwise, draw an arc! + else { + var x20 = x2 - x0, + y20 = y2 - y0, + l21_2 = x21 * x21 + y21 * y21, + l20_2 = x20 * x20 + y20 * y20, + l21 = Math.sqrt(l21_2), + l01 = Math.sqrt(l01_2), + l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), + t01 = l / l01, + t21 = l / l21; + + // If the start tangent is not coincident with (x0,y0), line to. + if (Math.abs(t01 - 1) > epsilon$1) { + this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); + } + + this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); + } + }, + arc: function(x, y, r, a0, a1, ccw) { + x = +x, y = +y, r = +r; + var dx = r * Math.cos(a0), + dy = r * Math.sin(a0), + x0 = x + dx, + y0 = y + dy, + cw = 1 ^ ccw, + da = ccw ? a0 - a1 : a1 - a0; - // These recursive directive definitions must be deferred. - formats.x = newFormat(locale_date, formats); - formats.X = newFormat(locale_time, formats); - formats.c = newFormat(locale_dateTime, formats); - utcFormats.x = newFormat(locale_date, utcFormats); - utcFormats.X = newFormat(locale_time, utcFormats); - utcFormats.c = newFormat(locale_dateTime, utcFormats); + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); - function newFormat(specifier, formats) { - return function(date) { - var string = [], - i = -1, - j = 0, - n = specifier.length, - c, - pad, - format; + // Is this path empty? Move to (x0,y0). + if (this._x1 === null) { + this._ += "M" + x0 + "," + y0; + } - if (!(date instanceof Date)) date = new Date(+date); + // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). + else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) { + this._ += "L" + x0 + "," + y0; + } - while (++i < n) { - if (specifier.charCodeAt(i) === 37) { - string.push(specifier.slice(j, i)); - if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); - else pad = c === "e" ? " " : "0"; - if (format = formats[c]) c = format(date, pad); - string.push(c); - j = i + 1; - } - } + // Is this arc empty? We’re done. + if (!r) return; - string.push(specifier.slice(j, i)); - return string.join(""); - }; + // Is this a complete circle? Draw two arcs to complete the circle. + if (da > tauEpsilon) { + this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); + } + + // Otherwise, draw an arc! + else { + if (da < 0) da = da % tau$2 + tau$2; + this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); + } + }, + rect: function(x, y, w, h) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; + }, + toString: function() { + return this._; } +}; - function newParse(specifier, newDate) { - return function(string) { - var d = newYear(1900), - i = parseSpecifier(d, specifier, string += "", 0); - if (i != string.length) return null; +function defaultSource(d) { + return d.source; +} - // The am-pm flag is 0 for AM, and 1 for PM. - if ("p" in d) d.H = d.H % 12 + d.p * 12; +function defaultTarget(d) { + return d.target; +} - // Convert day-of-week and week-of-year to day-of-year. - if ("W" in d || "U" in d) { - if (!("w" in d)) d.w = "W" in d ? 1 : 0; - var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); - d.m = 0; - d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$$1 + 5) % 7 : d.w + d.U * 7 - (day$$1 + 6) % 7; - } +function defaultRadius(d) { + return d.radius; +} - // If a time zone is specified, all fields are interpreted as UTC and then - // offset according to the specified time zone. - if ("Z" in d) { - d.H += d.Z / 100 | 0; - d.M += d.Z % 100; - return utcDate(d); - } +function defaultStartAngle(d) { + return d.startAngle; +} - // Otherwise, all fields are in local time. - return newDate(d); - }; - } +function defaultEndAngle(d) { + return d.endAngle; +} - function parseSpecifier(d, specifier, string, j) { - var i = 0, - n = specifier.length, - m = string.length, - c, - parse; +var ribbon = function() { + var source = defaultSource, + target = defaultTarget, + radius = defaultRadius, + startAngle = defaultStartAngle, + endAngle = defaultEndAngle, + context = null; - while (i < n) { - if (j >= m) return -1; - c = specifier.charCodeAt(i++); - if (c === 37) { - c = specifier.charAt(i++); - parse = parses[c in pads ? specifier.charAt(i++) : c]; - if (!parse || ((j = parse(d, string, j)) < 0)) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } + function ribbon() { + var buffer, + argv = slice$2.call(arguments), + s = source.apply(this, argv), + t = target.apply(this, argv), + sr = +radius.apply(this, (argv[0] = s, argv)), + sa0 = startAngle.apply(this, argv) - halfPi$1, + sa1 = endAngle.apply(this, argv) - halfPi$1, + sx0 = sr * cos(sa0), + sy0 = sr * sin(sa0), + tr = +radius.apply(this, (argv[0] = t, argv)), + ta0 = startAngle.apply(this, argv) - halfPi$1, + ta1 = endAngle.apply(this, argv) - halfPi$1; + + if (!context) context = buffer = path(); + + context.moveTo(sx0, sy0); + context.arc(0, 0, sr, sa0, sa1); + if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? + context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); + context.arc(0, 0, tr, ta0, ta1); } + context.quadraticCurveTo(0, 0, sx0, sy0); + context.closePath(); - return j; + if (buffer) return context = null, buffer + "" || null; } - function parsePeriod(d, string, i) { - var n = periodRe.exec(string.slice(i)); - return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } + ribbon.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius; + }; - function parseShortWeekday(d, string, i) { - var n = shortWeekdayRe.exec(string.slice(i)); - return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } + ribbon.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle; + }; - function parseWeekday(d, string, i) { - var n = weekdayRe.exec(string.slice(i)); - return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } + ribbon.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle; + }; - function parseShortMonth(d, string, i) { - var n = shortMonthRe.exec(string.slice(i)); - return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } + ribbon.source = function(_) { + return arguments.length ? (source = _, ribbon) : source; + }; - function parseMonth(d, string, i) { - var n = monthRe.exec(string.slice(i)); - return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } + ribbon.target = function(_) { + return arguments.length ? (target = _, ribbon) : target; + }; - function parseLocaleDateTime(d, string, i) { - return parseSpecifier(d, locale_dateTime, string, i); - } + ribbon.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; + }; - function parseLocaleDate(d, string, i) { - return parseSpecifier(d, locale_date, string, i); - } + return ribbon; +}; - function parseLocaleTime(d, string, i) { - return parseSpecifier(d, locale_time, string, i); - } +var prefix = "$"; - function formatShortWeekday(d) { - return locale_shortWeekdays[d.getDay()]; - } +function Map() {} - function formatWeekday(d) { - return locale_weekdays[d.getDay()]; +Map.prototype = map$1.prototype = { + constructor: Map, + has: function(key) { + return (prefix + key) in this; + }, + get: function(key) { + return this[prefix + key]; + }, + set: function(key, value) { + this[prefix + key] = value; + return this; + }, + remove: function(key) { + var property = prefix + key; + return property in this && delete this[property]; + }, + clear: function() { + for (var property in this) if (property[0] === prefix) delete this[property]; + }, + keys: function() { + var keys = []; + for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); + return keys; + }, + values: function() { + var values = []; + for (var property in this) if (property[0] === prefix) values.push(this[property]); + return values; + }, + entries: function() { + var entries = []; + for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); + return entries; + }, + size: function() { + var size = 0; + for (var property in this) if (property[0] === prefix) ++size; + return size; + }, + empty: function() { + for (var property in this) if (property[0] === prefix) return false; + return true; + }, + each: function(f) { + for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); } +}; - function formatShortMonth(d) { - return locale_shortMonths[d.getMonth()]; +function map$1(object, f) { + var map = new Map; + + // Copy constructor. + if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); + + // Index array by numeric index or specified key function. + else if (Array.isArray(object)) { + var i = -1, + n = object.length, + o; + + if (f == null) while (++i < n) map.set(i, object[i]); + else while (++i < n) map.set(f(o = object[i], i, object), o); } - function formatMonth(d) { - return locale_months[d.getMonth()]; - } + // Convert object to map. + else if (object) for (var key in object) map.set(key, object[key]); + + return map; +} + +var nest = function() { + var keys = [], + sortKeys = [], + sortValues, + rollup, + nest; - function formatPeriod(d) { - return locale_periods[+(d.getHours() >= 12)]; - } + function apply(array, depth, createResult, setResult) { + if (depth >= keys.length) return rollup != null + ? rollup(array) : (sortValues != null + ? array.sort(sortValues) + : array); - function formatUTCShortWeekday(d) { - return locale_shortWeekdays[d.getUTCDay()]; - } + var i = -1, + n = array.length, + key = keys[depth++], + keyValue, + value, + valuesByKey = map$1(), + values, + result = createResult(); - function formatUTCWeekday(d) { - return locale_weekdays[d.getUTCDay()]; - } + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { + values.push(value); + } else { + valuesByKey.set(keyValue, [value]); + } + } - function formatUTCShortMonth(d) { - return locale_shortMonths[d.getUTCMonth()]; - } + valuesByKey.each(function(values, key) { + setResult(result, key, apply(values, depth, createResult, setResult)); + }); - function formatUTCMonth(d) { - return locale_months[d.getUTCMonth()]; + return result; } - function formatUTCPeriod(d) { - return locale_periods[+(d.getUTCHours() >= 12)]; + function entries(map, depth) { + if (++depth > keys.length) return map; + var array, sortKey = sortKeys[depth - 1]; + if (rollup != null && depth >= keys.length) array = map.entries(); + else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); + return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; } - return { - format: function(specifier) { - var f = newFormat(specifier += "", formats); - f.toString = function() { return specifier; }; - return f; - }, - parse: function(specifier) { - var p = newParse(specifier += "", localDate); - p.toString = function() { return specifier; }; - return p; - }, - utcFormat: function(specifier) { - var f = newFormat(specifier += "", utcFormats); - f.toString = function() { return specifier; }; - return f; - }, - utcParse: function(specifier) { - var p = newParse(specifier, utcDate); - p.toString = function() { return specifier; }; - return p; - } + return nest = { + object: function(array) { return apply(array, 0, createObject, setObject); }, + map: function(array) { return apply(array, 0, createMap, setMap); }, + entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, + key: function(d) { keys.push(d); return nest; }, + sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, + sortValues: function(order) { sortValues = order; return nest; }, + rollup: function(f) { rollup = f; return nest; } }; -} - -var pads = {"-": "", "_": " ", "0": "0"}; -var numberRe = /^\s*\d+/; -var percentRe = /^%/; -var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; +}; -function pad(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 createObject() { + return {}; } -function requote(s) { - return s.replace(requoteRe, "\\$&"); +function setObject(object, key, value) { + object[key] = value; } -function formatRe(names) { - return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); +function createMap() { + return map$1(); } -function formatLookup(names) { - var map = {}, i = -1, n = names.length; - while (++i < n) map[names[i].toLowerCase()] = i; - return map; +function setMap(map, key, value) { + map.set(key, value); } -function parseWeekdayNumber(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 1)); - return n ? (d.w = +n[0], i + n[0].length) : -1; -} +function Set() {} -function parseWeekNumberSunday(d, string, i) { - var n = numberRe.exec(string.slice(i)); - return n ? (d.U = +n[0], i + n[0].length) : -1; -} +var proto = map$1.prototype; -function parseWeekNumberMonday(d, string, i) { - var n = numberRe.exec(string.slice(i)); - return n ? (d.W = +n[0], i + n[0].length) : -1; -} +Set.prototype = set$2.prototype = { + constructor: Set, + has: proto.has, + add: function(value) { + value += ""; + this[prefix + value] = value; + return this; + }, + remove: proto.remove, + clear: proto.clear, + values: proto.keys, + size: proto.size, + empty: proto.empty, + each: proto.each +}; -function parseFullYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 4)); - return n ? (d.y = +n[0], i + n[0].length) : -1; -} +function set$2(object, f) { + var set = new Set; -function parseYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; -} + // Copy constructor. + if (object instanceof Set) object.each(function(value) { set.add(value); }); -function parseZone(d, string, i) { - var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6)); - return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; -} + // Otherwise, assume it’s an array. + else if (object) { + var i = -1, n = object.length; + if (f == null) while (++i < n) set.add(object[i]); + else while (++i < n) set.add(f(object[i], i, object)); + } -function parseMonthNumber(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.m = n[0] - 1, i + n[0].length) : -1; + return set; } -function parseDayOfMonth(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.d = +n[0], i + n[0].length) : -1; -} +var keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; +}; -function parseDayOfYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 3)); - return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; -} +var values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; +}; -function parseHour24(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.H = +n[0], i + n[0].length) : -1; -} +var entries = function(map) { + var entries = []; + for (var key in map) entries.push({key: key, value: map[key]}); + return entries; +}; -function parseMinutes(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.M = +n[0], i + n[0].length) : -1; +function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); } -function parseSeconds(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.S = +n[0], i + n[0].length) : -1; +function customConverter(columns, f) { + var object = objectConverter(columns); + return function(row, i) { + return f(object(row), i, columns); + }; } -function parseMilliseconds(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 3)); - return n ? (d.L = +n[0], i + n[0].length) : -1; -} +// Compute unique columns in order of discovery. +function inferColumns(rows) { + var columnSet = Object.create(null), + columns = []; -function parseLiteralPercent(d, string, i) { - var n = percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; -} + rows.forEach(function(row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); -function formatDayOfMonth(d, p) { - return pad(d.getDate(), p, 2); + return columns; } -function formatHour24(d, p) { - return pad(d.getHours(), p, 2); -} +var dsv = function(delimiter) { + var reFormat = new RegExp("[\"" + delimiter + "\n]"), + delimiterCode = delimiter.charCodeAt(0); -function formatHour12(d, p) { - return pad(d.getHours() % 12 || 12, p, 2); -} + function parse(text, f) { + var convert, columns, rows = parseRows(text, function(row, i) { + if (convert) return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns; + return rows; + } + + function parseRows(text, f) { + var EOL = {}, // sentinel value for end-of-line + EOF = {}, // sentinel value for end-of-file + rows = [], // output rows + N = text.length, + I = 0, // current character index + n = 0, // the current line number + t, // the current token + eol; // is the current token followed by EOL? -function formatDayOfYear(d, p) { - return pad(1 + day.count(year(d), d), p, 3); -} + function token() { + if (I >= N) return EOF; // special case: end of file + if (eol) return eol = false, EOL; // special case: end of line -function formatMilliseconds(d, p) { - return pad(d.getMilliseconds(), p, 3); -} + // special case: quotes + var j = I, c; + 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; + 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, "\""); + } -function formatMonthNumber(d, p) { - return pad(d.getMonth() + 1, p, 2); -} + // common case: find next delimiter or newline + while (I < N) { + var k = 1; + c = text.charCodeAt(I++); + if (c === 10) eol = true; // \n + else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n + else if (c !== delimiterCode) continue; + return text.slice(j, I - k); + } -function formatMinutes(d, p) { - return pad(d.getMinutes(), p, 2); -} + // special case: last token before EOF + return text.slice(j); + } -function formatSeconds(d, p) { - return pad(d.getSeconds(), p, 2); -} + 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); + } -function formatWeekNumberSunday(d, p) { - return pad(sunday.count(year(d), d), p, 2); -} + return rows; + } -function formatWeekdayNumber(d) { - return d.getDay(); -} + function format(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { + return columns.map(function(column) { + return formatValue(row[column]); + }).join(delimiter); + })).join("\n"); + } -function formatWeekNumberMonday(d, p) { - return pad(monday.count(year(d), d), p, 2); -} + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } -function formatYear(d, p) { - return pad(d.getFullYear() % 100, p, 2); -} + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } -function formatFullYear(d, p) { - return pad(d.getFullYear() % 10000, p, 4); -} + function formatValue(text) { + return text == null ? "" + : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\"" + : text; + } -function formatZone(d) { - var z = d.getTimezoneOffset(); - return (z > 0 ? "-" : (z *= -1, "+")) - + pad(z / 60 | 0, "0", 2) - + pad(z % 60, "0", 2); -} + return { + parse: parse, + parseRows: parseRows, + format: format, + formatRows: formatRows + }; +}; -function formatUTCDayOfMonth(d, p) { - return pad(d.getUTCDate(), p, 2); -} +var csv = dsv(","); -function formatUTCHour24(d, p) { - return pad(d.getUTCHours(), p, 2); -} +var csvParse = csv.parse; +var csvParseRows = csv.parseRows; +var csvFormat = csv.format; +var csvFormatRows = csv.formatRows; -function formatUTCHour12(d, p) { - return pad(d.getUTCHours() % 12 || 12, p, 2); -} +var tsv = dsv("\t"); -function formatUTCDayOfYear(d, p) { - return pad(1 + utcDay.count(utcYear(d), d), p, 3); -} +var tsvParse = tsv.parse; +var tsvParseRows = tsv.parseRows; +var tsvFormat = tsv.format; +var tsvFormatRows = tsv.formatRows; -function formatUTCMilliseconds(d, p) { - return pad(d.getUTCMilliseconds(), p, 3); -} +var center$1 = function(x, y) { + var nodes; -function formatUTCMonthNumber(d, p) { - return pad(d.getUTCMonth() + 1, p, 2); -} + if (x == null) x = 0; + if (y == null) y = 0; -function formatUTCMinutes(d, p) { - return pad(d.getUTCMinutes(), p, 2); -} + function force() { + var i, + n = nodes.length, + node, + sx = 0, + sy = 0; -function formatUTCSeconds(d, p) { - return pad(d.getUTCSeconds(), p, 2); -} + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x, sy += node.y; + } -function formatUTCWeekNumberSunday(d, p) { - return pad(utcSunday.count(utcYear(d), d), p, 2); -} + for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { + node = nodes[i], node.x -= sx, node.y -= sy; + } + } -function formatUTCWeekdayNumber(d) { - return d.getUTCDay(); -} + force.initialize = function(_) { + nodes = _; + }; -function formatUTCWeekNumberMonday(d, p) { - return pad(utcMonday.count(utcYear(d), d), p, 2); -} + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; -function formatUTCYear(d, p) { - return pad(d.getUTCFullYear() % 100, p, 2); -} + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; -function formatUTCFullYear(d, p) { - return pad(d.getUTCFullYear() % 10000, p, 4); -} + return force; +}; -function formatUTCZone() { - return "+0000"; -} +var constant$6 = function(x) { + return function() { + return x; + }; +}; -function formatLiteralPercent() { - return "%"; -} +var jiggle = function() { + return (Math.random() - 0.5) * 1e-6; +}; -var locale$2; +var tree_add = function(d) { + var x = +this._x.call(null, d), + y = +this._y.call(null, d); + return add(this.cover(x, y), x, y, d); +}; +function add(tree, x, y, d) { + if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + x1 = tree._x1, + y1 = tree._y1, + xm, + ym, + xp, + yp, + right, + bottom, + i, + j; + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; + } -defaultLocale$1({ - dateTime: "%x, %X", - date: "%-m/%-d/%Y", - time: "%-I:%M:%S %p", - 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"] -}); + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; -function defaultLocale$1(definition) { - locale$2 = formatLocale$1(definition); - exports.timeFormat = locale$2.format; - exports.timeParse = locale$2.parse; - exports.utcFormat = locale$2.utcFormat; - exports.utcParse = locale$2.utcParse; - return locale$2; + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; } -var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; +function addAll(data) { + var d, i, n = data.length, + x, + y, + xz = new Array(n), + yz = new Array(n), + x0 = Infinity, + y0 = Infinity, + x1 = -Infinity, + y1 = -Infinity; -function formatIsoNative(date) { - return date.toISOString(); -} + // Compute the points and their extent. + for (i = 0; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; + xz[i] = x; + yz[i] = y; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; + } -var formatIso = Date.prototype.toISOString - ? formatIsoNative - : exports.utcFormat(isoSpecifier); + // If there were no (valid) points, inherit the existing extent. + if (x1 < x0) x0 = this._x0, x1 = this._x1; + if (y1 < y0) y0 = this._y0, y1 = this._y1; -function parseIsoNative(string) { - var date = new Date(string); - return isNaN(date) ? null : date; -} + // Expand the tree to cover the new points. + this.cover(x0, y0).cover(x1, y1); -var parseIso = +new Date("2000-01-01T00:00:00.000Z") - ? parseIsoNative - : exports.utcParse(isoSpecifier); + // Add the new points. + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } -var array$2 = Array.prototype; + return this; +} -var map$3 = array$2.map; -var slice$3 = array$2.slice; +var tree_cover = function(x, y) { + if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points -var implicit = {name: "implicit"}; + var x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1; -function ordinal(range) { - var index = map$1(), - domain = [], - unknown = implicit; + // If the quadtree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing quadrant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + } - range = range == null ? [] : slice$3.call(range); + // Otherwise, double repeatedly to cover. + else if (x0 > x || x > x1 || y0 > y || y > y1) { + var z = x1 - x0, + node = this._root, + parent, + i; - function scale(d) { - var key = d + "", i = index.get(key); - if (!i) { - if (unknown !== implicit) return unknown; - index.set(key, i = domain.push(d)); + switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { + case 0: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); + break; + } + case 1: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); + break; + } + case 2: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); + break; + } + case 3: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); + break; + } } - return range[(i - 1) % range.length]; - } - scale.domain = function(_) { - if (!arguments.length) return domain.slice(); - domain = [], index = map$1(); - var i = -1, n = _.length, d, key; - while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); - return scale; - }; + if (this._root && this._root.length) this._root = node; + } - scale.range = function(_) { - return arguments.length ? (range = slice$3.call(_), scale) : range.slice(); - }; + // If the quadtree covers the point already, just return. + else return this; - scale.unknown = function(_) { - return arguments.length ? (unknown = _, scale) : unknown; - }; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; +}; - scale.copy = function() { - return ordinal() - .domain(domain) - .range(range) - .unknown(unknown); - }; +var tree_data = function() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; +}; - return scale; -} +var tree_extent = function(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; +}; -function band() { - var scale = ordinal().unknown(undefined), - domain = scale.domain, - ordinalRange = scale.range, - range$$1 = [0, 1], - step, - bandwidth, - round = false, - paddingInner = 0, - paddingOuter = 0, - align = 0.5; +var Quad = function(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; +}; - delete scale.unknown; +var tree_find = function(x, y, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + x1, + y1, + x2, + y2, + x3 = this._x1, + y3 = this._y1, + quads = [], + node = this._root, + q, + i; - function rescale() { - var n = domain().length, - reverse = range$$1[1] < range$$1[0], - start = range$$1[reverse - 0], - stop = range$$1[1 - reverse]; - step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); - if (round) step = Math.floor(step); - start += (stop - start - step * (n - paddingInner)) * align; - bandwidth = step * (1 - paddingInner); - if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); - var values = range(n).map(function(i) { return start + step * i; }); - return ordinalRange(reverse ? values.reverse() : values); + if (node) quads.push(new Quad(node, x0, y0, x3, y3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius, y0 = y - radius; + x3 = x + radius, y3 = y + radius; + radius *= radius; } - scale.domain = function(_) { - return arguments.length ? (domain(_), rescale()) : domain(); - }; + while (q = quads.pop()) { - scale.range = function(_) { - return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice(); - }; + // Stop searching if this quadrant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0) continue; - scale.rangeRound = function(_) { - return range$$1 = [+_[0], +_[1]], round = true, rescale(); - }; + // Bisect the current quadrant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2; - scale.bandwidth = function() { - return bandwidth; - }; + quads.push( + new Quad(node[3], xm, ym, x2, y2), + new Quad(node[2], x1, ym, xm, y2), + new Quad(node[1], xm, y1, x2, ym), + new Quad(node[0], x1, y1, xm, ym) + ); - scale.step = function() { - return step; - }; + // Visit the closest quadrant first. + if (i = (y >= ym) << 1 | (x >= xm)) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } - scale.round = function(_) { - return arguments.length ? (round = !!_, rescale()) : round; - }; + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = node.data; + } + } + } - scale.padding = function(_) { - return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; - }; + return data; +}; + +var tree_remove = function(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points - scale.paddingInner = function(_) { - return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; - }; + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1, + x, + y, + xm, + ym, + right, + bottom, + i, + j; - scale.paddingOuter = function(_) { - return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter; - }; + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; - scale.align = function(_) { - return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; - }; + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; + } - scale.copy = function() { - return band() - .domain(domain()) - .range(range$$1) - .round(round) - .paddingInner(paddingInner) - .paddingOuter(paddingOuter) - .align(align); - }; + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; - return rescale(); -} + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; -function pointish(scale) { - var copy = scale.copy; + // If this is the root point, remove it. + if (!parent) return this._root = next, this; - scale.padding = scale.paddingOuter; - delete scale.paddingInner; - delete scale.paddingOuter; + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; - scale.copy = function() { - return pointish(copy()); - }; + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) + && node === (parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } - return scale; -} + return this; +}; -function point$4() { - return pointish(band().paddingInner(1)); +function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; } -var constant$4 = function(x) { - return function() { - return x; - }; +var tree_root = function() { + return this._root; }; -var number$1 = function(x) { - return +x; +var tree_size = function() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; }; -var unit = [0, 1]; +var tree_visit = function(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + } + } + return this; +}; -function deinterpolateLinear(a, b) { - return (b -= (a = +a)) - ? function(x) { return (x - a) / b; } - : constant$4(b); -} +var tree_visitAfter = function(callback) { + var quads = [], next = [], q; + if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; +}; -function deinterpolateClamp(deinterpolate) { - return function(a, b) { - var d = deinterpolate(a = +a, b = +b); - return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; - }; +function defaultX(d) { + return d[0]; } -function reinterpolateClamp(reinterpolate) { - return function(a, b) { - var r = reinterpolate(a = +a, b = +b); - return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; - }; -} +var tree_x = function(_) { + return arguments.length ? (this._x = _, this) : this._x; +}; -function bimap(domain, range$$1, deinterpolate, reinterpolate) { - var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1]; - if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); - else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); - return function(x) { return r0(d0(x)); }; +function defaultY(d) { + return d[1]; } -function polymap(domain, range$$1, deinterpolate, reinterpolate) { - var j = Math.min(domain.length, range$$1.length) - 1, - d = new Array(j), - r = new Array(j), - i = -1; - - // Reverse descending domains. - if (domain[j] < domain[0]) { - domain = domain.slice().reverse(); - range$$1 = range$$1.slice().reverse(); - } +var tree_y = function(_) { + return arguments.length ? (this._y = _, this) : this._y; +}; - while (++i < j) { - d[i] = deinterpolate(domain[i], domain[i + 1]); - r[i] = reinterpolate(range$$1[i], range$$1[i + 1]); - } +function quadtree(nodes, x, y) { + var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); +} - return function(x) { - var i = bisectRight(domain, x, 1, j) - 1; - return r[i](d[i](x)); - }; +function Quadtree(x, y, x0, y0, x1, y1) { + this._x = x; + this._y = y; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = undefined; } -function copy(source, target) { - return target - .domain(source.domain()) - .range(source.range()) - .interpolate(source.interpolate()) - .clamp(source.clamp()); +function leaf_copy(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; } -// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. -// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. -function continuous(deinterpolate, reinterpolate) { - var domain = unit, - range$$1 = unit, - interpolate$$1 = interpolate, - clamp = false, - piecewise, - output, - input; +var treeProto = quadtree.prototype = Quadtree.prototype; - function rescale() { - piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap; - output = input = null; - return scale; - } +treeProto.copy = function() { + var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + node = this._root, + nodes, + child; - function scale(x) { - return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy(node), copy; + + nodes = [{source: node, target: copy._root = new Array(4)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); + else node.target[i] = leaf_copy(child); + } + } } - scale.invert = function(y) { - return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); - }; + return copy; +}; - scale.domain = function(_) { - return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice(); - }; +treeProto.add = tree_add; +treeProto.addAll = addAll; +treeProto.cover = tree_cover; +treeProto.data = tree_data; +treeProto.extent = tree_extent; +treeProto.find = tree_find; +treeProto.remove = tree_remove; +treeProto.removeAll = removeAll; +treeProto.root = tree_root; +treeProto.size = tree_size; +treeProto.visit = tree_visit; +treeProto.visitAfter = tree_visitAfter; +treeProto.x = tree_x; +treeProto.y = tree_y; - scale.range = function(_) { - return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice(); - }; +function x(d) { + return d.x + d.vx; +} - scale.rangeRound = function(_) { - return range$$1 = slice$3.call(_), interpolate$$1 = interpolateRound, rescale(); - }; +function y(d) { + return d.y + d.vy; +} - scale.clamp = function(_) { - return arguments.length ? (clamp = !!_, rescale()) : clamp; - }; +var collide = function(radius) { + var nodes, + radii, + strength = 1, + iterations = 1; - scale.interpolate = function(_) { - return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; - }; + if (typeof radius !== "function") radius = constant$6(radius == null ? 1 : +radius); - return rescale(); -} + function force() { + var i, n = nodes.length, + tree, + node, + xi, + yi, + ri, + ri2; -var tickFormat = function(domain, count, specifier) { - var start = domain[0], - stop = domain[domain.length - 1], - step = tickStep(start, stop, count == null ? 10 : count), - precision; - specifier = formatSpecifier(specifier == null ? ",f" : specifier); - switch (specifier.type) { - case "s": { - var value = Math.max(Math.abs(start), Math.abs(stop)); - if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision; - return exports.formatPrefix(specifier, value); + for (var k = 0; k < iterations; ++k) { + tree = quadtree(nodes, x, y).visitAfter(prepare); + for (i = 0; i < n; ++i) { + node = nodes[i]; + ri = radii[node.index], ri2 = ri * ri; + xi = node.x + node.vx; + yi = node.y + node.vy; + tree.visit(apply); + } } - case "": - case "e": - case "g": - case "p": - case "r": { - if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); - break; + + function apply(quad, x0, y0, x1, y1) { + var data = quad.data, rj = quad.r, r = ri + rj; + if (data) { + if (data.index > node.index) { + var x = xi - data.x - data.vx, + y = yi - data.y - data.vy, + l = x * x + y * y; + if (l < r * r) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + l = (r - (l = Math.sqrt(l))) / l * strength; + node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); + node.vy += (y *= l) * r; + data.vx -= x * (r = 1 - r); + data.vy -= y * r; + } + } + return; + } + return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; } - case "f": - case "%": { - if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; - break; + } + + function prepare(quad) { + if (quad.data) return quad.r = radii[quad.data.index]; + for (var i = quad.r = 0; i < 4; ++i) { + if (quad[i] && quad[i].r > quad.r) { + quad.r = quad[i].r; + } } } - return exports.format(specifier); -}; -function linearish(scale) { - var domain = scale.domain; + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + radii = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes); + } - scale.ticks = function(count) { - var d = domain(); - return ticks(d[0], d[d.length - 1], count == null ? 10 : count); + force.initialize = function(_) { + nodes = _; + initialize(); }; - scale.tickFormat = function(count, specifier) { - return tickFormat(domain(), count, specifier); + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; }; - scale.nice = function(count) { - var d = domain(), - i = d.length - 1, - n = count == null ? 10 : count, - start = d[0], - stop = d[i], - step = tickStep(start, stop, n); - - if (step) { - step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n); - d[0] = Math.floor(start / step) * step; - d[i] = Math.ceil(stop / step) * step; - domain(d); - } - - return scale; + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; }; - return scale; -} - -function linear$2() { - var scale = continuous(deinterpolateLinear, interpolateNumber); - - scale.copy = function() { - return copy(scale, linear$2()); + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius; }; - return linearish(scale); -} - -function identity$4() { - var domain = [0, 1]; - - function scale(x) { - return +x; - } - - scale.invert = scale; - - scale.domain = scale.range = function(_) { - return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice(); - }; + return force; +}; - scale.copy = function() { - return identity$4().domain(domain); - }; +function index(d) { + return d.index; +} - return linearish(scale); +function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) throw new Error("missing: " + nodeId); + return node; } -var nice = function(domain, interval) { - domain = domain.slice(); +var link = function(links) { + var id = index, + strength = defaultStrength, + strengths, + distance = constant$6(30), + distances, + nodes, + count, + bias, + iterations = 1; - var i0 = 0, - i1 = domain.length - 1, - x0 = domain[i0], - x1 = domain[i1], - t; + if (links == null) links = []; - if (x1 < x0) { - t = i0, i0 = i1, i1 = t; - t = x0, x0 = x1, x1 = t; + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); } - domain[i0] = interval.floor(x0); - domain[i1] = interval.ceil(x1); - return domain; -}; + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - distances[i]) / l * alpha * strengths[i]; + x *= l, y *= l; + target.vx -= x * (b = bias[i]); + target.vy -= y * b; + source.vx += x * (b = 1 - b); + source.vy += y * b; + } + } + } -function deinterpolate(a, b) { - return (b = Math.log(b / a)) - ? function(x) { return Math.log(x / a) / b; } - : constant$4(b); -} + function initialize() { + if (!nodes) return; -function reinterpolate(a, b) { - return a < 0 - ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); } - : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); }; -} + var i, + n = nodes.length, + m = links.length, + nodeById = map$1(nodes, id), + link; -function pow10(x) { - return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; -} + for (i = 0, count = new Array(n); i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") link.source = find(nodeById, link.source); + if (typeof link.target !== "object") link.target = find(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } -function powp(base) { - return base === 10 ? pow10 - : base === Math.E ? Math.exp - : function(x) { return Math.pow(base, x); }; -} + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } -function logp(base) { - return base === Math.E ? Math.log - : base === 10 && Math.log10 - || base === 2 && Math.log2 - || (base = Math.log(base), function(x) { return Math.log(x) / base; }); -} + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } -function reflect(f) { - return function(x) { - return -f(-x); - }; -} + function initializeStrength() { + if (!nodes) return; -function log() { - var scale = continuous(deinterpolate, reinterpolate).domain([1, 10]), - domain = scale.domain, - base = 10, - logs = logp(10), - pows = powp(10); + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } - function rescale() { - logs = logp(base), pows = powp(base); - if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows); - return scale; + function initializeDistance() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } } - scale.base = function(_) { - return arguments.length ? (base = +_, rescale()) : base; + force.initialize = function(_) { + nodes = _; + initialize(); }; - scale.domain = function(_) { - return arguments.length ? (domain(_), rescale()) : domain(); + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; }; - scale.ticks = function(count) { - var d = domain(), - u = d[0], - v = d[d.length - 1], - r; - - if (r = v < u) i = u, u = v, v = i; - - var i = logs(u), - j = logs(v), - p, - k, - t, - n = count == null ? 10 : +count, - z = []; - - if (!(base % 1) && j - i < n) { - i = Math.round(i) - 1, j = Math.round(j) + 1; - if (u > 0) for (; i < j; ++i) { - for (k = 1, p = pows(i); k < base; ++k) { - t = p * k; - if (t < u) continue; - if (t > v) break; - z.push(t); - } - } else for (; i < j; ++i) { - for (k = base - 1, p = pows(i); k >= 1; --k) { - t = p * k; - if (t < u) continue; - if (t > v) break; - z.push(t); - } - } - } else { - z = ticks(i, j, Math.min(j - i, n)).map(pows); - } - - return r ? z.reverse() : z; + force.id = function(_) { + return arguments.length ? (id = _, force) : id; }; - scale.tickFormat = function(count, specifier) { - if (specifier == null) specifier = base === 10 ? ".0e" : ","; - if (typeof specifier !== "function") specifier = exports.format(specifier); - if (count === Infinity) return specifier; - if (count == null) count = 10; - var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? - return function(d) { - var i = d / pows(Math.round(logs(d))); - if (i * base < base - 0.5) i *= base; - return i <= k ? specifier(d) : ""; - }; + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; }; - scale.nice = function() { - return domain(nice(domain(), { - floor: function(x) { return pows(Math.floor(logs(x))); }, - ceil: function(x) { return pows(Math.ceil(logs(x))); } - })); + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initializeStrength(), force) : strength; }; - scale.copy = function() { - return copy(scale, log().base(base)); + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant$6(+_), initializeDistance(), force) : distance; }; - return scale; -} + return force; +}; -function raise(x, exponent) { - return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); +function x$1(d) { + return d.x; } -function pow() { - var exponent = 1, - scale = continuous(deinterpolate, reinterpolate), - domain = scale.domain; +function y$1(d) { + return d.y; +} - function deinterpolate(a, b) { - return (b = raise(b, exponent) - (a = raise(a, exponent))) - ? function(x) { return (raise(x, exponent) - a) / b; } - : constant$4(b); - } +var initialRadius = 10; +var initialAngle = Math.PI * (3 - Math.sqrt(5)); - function reinterpolate(a, b) { - b = raise(b, exponent) - (a = raise(a, exponent)); - return function(t) { return raise(a + b * t, 1 / exponent); }; - } +var simulation = function(nodes) { + var simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = map$1(), + stepper = timer(step), + event = dispatch("tick", "end"); - scale.exponent = function(_) { - return arguments.length ? (exponent = +_, domain(domain())) : exponent; - }; + if (nodes == null) nodes = []; - scale.copy = function() { - return copy(scale, pow().exponent(exponent)); - }; + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } - return linearish(scale); -} + function tick() { + var i, n = nodes.length, node; -function sqrt() { - return pow().exponent(0.5); -} + alpha += (alphaTarget - alpha) * alphaDecay; -function quantile$$1() { - var domain = [], - range$$1 = [], - thresholds = []; + forces.each(function(force) { + force(alpha); + }); - function rescale() { - var i = 0, n = Math.max(1, range$$1.length); - thresholds = new Array(n - 1); - while (++i < n) thresholds[i - 1] = threshold(domain, i / n); - return scale; + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) node.x += node.vx *= velocityDecay; + else node.x = node.fx, node.vx = 0; + if (node.fy == null) node.y += node.vy *= velocityDecay; + else node.y = node.fy, node.vy = 0; + } } - function scale(x) { - if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)]; + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } } - scale.invertExtent = function(y) { - var i = range$$1.indexOf(y); - return i < 0 ? [NaN, NaN] : [ - i > 0 ? thresholds[i - 1] : domain[0], - i < thresholds.length ? thresholds[i] : domain[domain.length - 1] - ]; - }; - - scale.domain = function(_) { - if (!arguments.length) return domain.slice(); - domain = []; - for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d); - domain.sort(ascending); - return rescale(); - }; + function initializeForce(force) { + if (force.initialize) force.initialize(nodes); + return force; + } - scale.range = function(_) { - return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice(); - }; + initializeNodes(); - scale.quantiles = function() { - return thresholds.slice(); - }; + return simulation = { + tick: tick, - scale.copy = function() { - return quantile$$1() - .domain(domain) - .range(range$$1); - }; + restart: function() { + return stepper.restart(step), simulation; + }, - return scale; -} + stop: function() { + return stepper.stop(), simulation; + }, -function quantize$1() { - var x0 = 0, - x1 = 1, - n = 1, - domain = [0.5], - range$$1 = [0, 1]; + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; + }, - function scale(x) { - if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; - } + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, - function rescale() { - var i = -1; - domain = new Array(n); - while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); - return scale; - } + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, - scale.domain = function(_) { - return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; - }; + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, - scale.range = function(_) { - return arguments.length ? (n = (range$$1 = slice$3.call(_)).length - 1, rescale()) : range$$1.slice(); - }; + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, - scale.invertExtent = function(y) { - var i = range$$1.indexOf(y); - return i < 0 ? [NaN, NaN] - : i < 1 ? [x0, domain[0]] - : i >= n ? [domain[n - 1], x1] - : [domain[i - 1], domain[i]]; - }; + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, - scale.copy = function() { - return quantize$1() - .domain([x0, x1]) - .range(range$$1); - }; + force: function(name, _) { + return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, - return linearish(scale); -} + find: function(x, y, radius) { + var i = 0, + n = nodes.length, + dx, + dy, + d2, + node, + closest; -function threshold$1() { - var domain = [0.5], - range$$1 = [0, 1], - n = 1; + if (radius == null) radius = Infinity; + else radius *= radius; - function scale(x) { - if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; - } + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) closest = node, radius = d2; + } - scale.domain = function(_) { - return arguments.length ? (domain = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice(); - }; + return closest; + }, - scale.range = function(_) { - return arguments.length ? (range$$1 = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice(); + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } }; +}; - scale.invertExtent = function(y) { - var i = range$$1.indexOf(y); - return [domain[i - 1], domain[i]]; - }; +var manyBody = function() { + var nodes, + node, + alpha, + strength = constant$6(-30), + strengths, + distanceMin2 = 1, + distanceMax2 = Infinity, + theta2 = 0.81; - scale.copy = function() { - return threshold$1() - .domain(domain) - .range(range$$1); - }; + function force(_) { + var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); + } - return scale; -} + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + strengths = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); + } -var durationSecond$1 = 1000; -var durationMinute$1 = durationSecond$1 * 60; -var durationHour$1 = durationMinute$1 * 60; -var durationDay$1 = durationHour$1 * 24; -var durationWeek$1 = durationDay$1 * 7; -var durationMonth = durationDay$1 * 30; -var durationYear = durationDay$1 * 365; + function accumulate(quad) { + var strength = 0, q, c, x$$1, y$$1, i; -function date$1(t) { - return new Date(t); -} + // For internal nodes, accumulate forces from child quadrants. + if (quad.length) { + for (x$$1 = y$$1 = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c = q.value)) { + strength += c, x$$1 += c * q.x, y$$1 += c * q.y; + } + } + quad.x = x$$1 / strength; + quad.y = y$$1 / strength; + } -function number$2(t) { - return t instanceof Date ? +t : +new Date(+t); -} + // For leaf nodes, accumulate forces from coincident quadrants. + else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do strength += strengths[q.data.index]; + while (q = q.next); + } -function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) { - var scale = continuous(deinterpolateLinear, interpolateNumber), - invert = scale.invert, - domain = scale.domain; + quad.value = strength; + } - var formatMillisecond = format(".%L"), - formatSecond = format(":%S"), - formatMinute = format("%I:%M"), - formatHour = format("%I %p"), - formatDay = format("%a %d"), - formatWeek = format("%b %d"), - formatMonth = format("%B"), - formatYear = format("%Y"); + function apply(quad, x1, _, x2) { + if (!quad.value) return true; - var tickIntervals = [ - [second$$1, 1, durationSecond$1], - [second$$1, 5, 5 * durationSecond$1], - [second$$1, 15, 15 * durationSecond$1], - [second$$1, 30, 30 * durationSecond$1], - [minute$$1, 1, durationMinute$1], - [minute$$1, 5, 5 * durationMinute$1], - [minute$$1, 15, 15 * durationMinute$1], - [minute$$1, 30, 30 * durationMinute$1], - [ hour$$1, 1, durationHour$1 ], - [ hour$$1, 3, 3 * durationHour$1 ], - [ hour$$1, 6, 6 * durationHour$1 ], - [ hour$$1, 12, 12 * durationHour$1 ], - [ day$$1, 1, durationDay$1 ], - [ day$$1, 2, 2 * durationDay$1 ], - [ week, 1, durationWeek$1 ], - [ month$$1, 1, durationMonth ], - [ month$$1, 3, 3 * durationMonth ], - [ year$$1, 1, durationYear ] - ]; + var x$$1 = quad.x - node.x, + y$$1 = quad.y - node.y, + w = x2 - x1, + l = x$$1 * x$$1 + y$$1 * y$$1; - function tickFormat(date) { - return (second$$1(date) < date ? formatMillisecond - : minute$$1(date) < date ? formatSecond - : hour$$1(date) < date ? formatMinute - : day$$1(date) < date ? formatHour - : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek) - : year$$1(date) < date ? formatMonth - : formatYear)(date); - } + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; + if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + node.vx += x$$1 * quad.value * alpha / l; + node.vy += y$$1 * quad.value * alpha / l; + } + return true; + } - function tickInterval(interval, start, stop, step) { - if (interval == null) interval = 10; + // Otherwise, process points directly. + else if (quad.length || l >= distanceMax2) return; - // If a desired tick count is specified, pick a reasonable tick interval - // based on the extent of the domain and a rough estimate of tick size. - // Otherwise, assume interval is already a time interval and use it. - if (typeof interval === "number") { - var target = Math.abs(stop - start) / interval, - i = bisector(function(i) { return i[2]; }).right(tickIntervals, target); - if (i === tickIntervals.length) { - step = tickStep(start / durationYear, stop / durationYear, interval); - interval = year$$1; - } else if (i) { - i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; - step = i[1]; - interval = i[0]; - } else { - step = tickStep(start, stop, interval); - interval = millisecond$$1; - } + // Limit forces for very close nodes; randomize direction if coincident. + if (quad.data !== node || quad.next) { + if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; + if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); } - return step == null ? interval : interval.every(step); + do if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x$$1 * w; + node.vy += y$$1 * w; + } while (quad = quad.next); } - scale.invert = function(y) { - return new Date(invert(y)); - }; - - scale.domain = function(_) { - return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1); + force.initialize = function(_) { + nodes = _; + initialize(); }; - scale.ticks = function(interval, step) { - var d = domain(), - t0 = d[0], - t1 = d[d.length - 1], - r = t1 < t0, - t; - if (r) t = t0, t0 = t1, t1 = t; - t = tickInterval(interval, t0, t1, step); - t = t ? t.range(t0, t1 + 1) : []; // inclusive stop - return r ? t.reverse() : t; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; }; - scale.tickFormat = function(count, specifier) { - return specifier == null ? tickFormat : format(specifier); + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); }; - scale.nice = function(interval, step) { - var d = domain(); - return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) - ? domain(nice(d, interval)) - : scale; + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); }; - scale.copy = function() { - return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format)); + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); }; - return scale; -} - -var time = function() { - return calendar(year, month, sunday, day, hour, minute, second, millisecond, exports.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); -}; - -var utcTime = function() { - return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, exports.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]); -}; - -var colors = function(s) { - return s.match(/.{6}/g).map(function(x) { - return "#" + x; - }); + return force; }; -var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); - -var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); - -var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); - -var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); - -var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0)); - -var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); +var x$2 = function(x) { + var strength = constant$6(0.1), + nodes, + strengths, + xz; -var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); + if (typeof x !== "function") x = constant$6(x == null ? 0 : +x); -var rainbow = cubehelix(); + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; + } + } -var rainbow$1 = function(t) { - if (t < 0 || t > 1) t -= Math.floor(t); - var ts = Math.abs(t - 0.5); - rainbow.h = 360 * t - 100; - rainbow.s = 1.5 - 1.5 * ts; - rainbow.l = 0.8 - 0.9 * ts; - return rainbow + ""; -}; + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + xz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } -function ramp(range) { - var n = range.length; - return function(t) { - return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + force.initialize = function(_) { + nodes = _; + initialize(); }; -} -var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; + }; -var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); + force.x = function(_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : x; + }; -var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); + return force; +}; -var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); +var y$2 = function(y) { + var strength = constant$6(0.1), + nodes, + strengths, + yz; -function sequential(interpolator) { - var x0 = 0, - x1 = 1, - clamp = false; + if (typeof y !== "function") y = constant$6(y == null ? 0 : +y); - function scale(x) { - var t = (x - x0) / (x1 - x0); - return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t); + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; + } } - scale.domain = function(_) { - return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1]; - }; + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + yz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } - scale.clamp = function(_) { - return arguments.length ? (clamp = !!_, scale) : clamp; + force.initialize = function(_) { + nodes = _; + initialize(); }; - scale.interpolator = function(_) { - return arguments.length ? (interpolator = _, scale) : interpolator; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; }; - scale.copy = function() { - return sequential(interpolator).domain([x0, x1]).clamp(clamp); + force.y = function(_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : y; }; - return linearish(scale); -} + return force; +}; -var xhtml = "http://www.w3.org/1999/xhtml"; +// Computes the decimal coefficient and exponent of the specified number x with +// significant digits p, where x is positive and p is in [1, 21] or undefined. +// For example, formatDecimal(1.23) returns ["123", 0]. +var formatDecimal = function(x, p) { + if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity + var i, coefficient = x.slice(0, i); -var namespaces = { - svg: "http://www.w3.org/2000/svg", - xhtml: xhtml, - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" + // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ + // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x.slice(i + 1) + ]; }; -var namespace = function(name) { - var prefix = name += "", i = prefix.indexOf(":"); - if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); - return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; +var exponent$1 = function(x) { + return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; }; -function creatorInherit(name) { - return function() { - var document = this.ownerDocument, - uri = this.namespaceURI; - return uri === xhtml && document.documentElement.namespaceURI === xhtml - ? document.createElement(name) - : document.createElementNS(uri, name); - }; -} +var formatGroup = function(grouping, thousands) { + return function(value, width) { + var i = value.length, + t = [], + j = 0, + g = grouping[0], + length = 0; -function creatorFixed(fullname) { - return function() { - return this.ownerDocument.createElementNS(fullname.space, fullname.local); - }; -} + 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 = grouping[j = (j + 1) % grouping.length]; + } -var creator = function(name) { - var fullname = namespace(name); - return (fullname.local - ? creatorFixed - : creatorInherit)(fullname); + return t.reverse().join(thousands); + }; }; -var nextId = 0; +var formatDefault = function(x, p) { + x = x.toPrecision(p); -function local() { - return new Local; -} + out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { + switch (x[i]) { + case ".": i0 = i1 = i; break; + case "0": if (i0 === 0) i0 = i; i1 = i; break; + case "e": break out; + default: if (i0 > 0) i0 = 0; break; + } + } -function Local() { - this._ = "@" + (++nextId).toString(36); -} + return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; +}; -Local.prototype = local.prototype = { - constructor: Local, - get: function(node) { - var id = this._; - while (!(id in node)) if (!(node = node.parentNode)) return; - return node[id]; - }, - set: function(node, value) { - return node[this._] = value; - }, - remove: function(node) { - return this._ in node && delete node[this._]; - }, - toString: function() { - return this._; - } +var prefixExponent; + +var formatPrefixAuto = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1], + i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, + n = coefficient.length; + return i === n ? coefficient + : i > n ? coefficient + new Array(i - n + 1).join("0") + : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) + : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! }; -var matcher = function(selector) { - return function() { - return this.matches(selector); - }; +var formatRounded = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1]; + return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient + : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) + : coefficient + new Array(exponent - coefficient.length + 2).join("0"); }; -if (typeof document !== "undefined") { - var element = document.documentElement; - if (!element.matches) { - var vendorMatches = element.webkitMatchesSelector - || element.msMatchesSelector - || element.mozMatchesSelector - || element.oMatchesSelector; - matcher = function(selector) { - return function() { - return vendorMatches.call(this, selector); - }; - }; - } -} +var formatTypes = { + "": formatDefault, + "%": function(x, p) { return (x * 100).toFixed(p); }, + "b": function(x) { return Math.round(x).toString(2); }, + "c": function(x) { return x + ""; }, + "d": function(x) { return Math.round(x).toString(10); }, + "e": function(x, p) { return x.toExponential(p); }, + "f": function(x, p) { return x.toFixed(p); }, + "g": function(x, p) { return x.toPrecision(p); }, + "o": function(x) { return Math.round(x).toString(8); }, + "p": function(x, p) { return formatRounded(x * 100, p); }, + "r": formatRounded, + "s": formatPrefixAuto, + "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, + "x": function(x) { return Math.round(x).toString(16); } +}; -var matcher$1 = matcher; +// [[fill]align][sign][symbol][0][width][,][.precision][type] +var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; -var filterEvents = {}; +var formatSpecifier = function(specifier) { + return new FormatSpecifier(specifier); +}; -exports.event = null; +function FormatSpecifier(specifier) { + if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); -if (typeof document !== "undefined") { - var element$1 = document.documentElement; - if (!("onmouseenter" in element$1)) { - filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; - } -} + var match, + fill = match[1] || " ", + align = match[2] || ">", + sign = match[3] || "-", + symbol = match[4] || "", + zero = !!match[5], + width = match[6] && +match[6], + comma = !!match[7], + precision = match[8] && +match[8].slice(1), + type = match[9] || ""; -function filterContextListener(listener, index, group) { - listener = contextListener(listener, index, group); - return function(event) { - var related = event.relatedTarget; - if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { - listener.call(this, event); - } - }; -} + // The "n" type is an alias for ",g". + if (type === "n") comma = true, type = "g"; -function contextListener(listener, index, group) { - return function(event1) { - var event0 = exports.event; // Events can be reentrant (e.g., focus). - exports.event = event1; - try { - listener.call(this, this.__data__, index, group); - } finally { - exports.event = event0; - } - }; + // Map invalid types to the default format. + else if (!formatTypes[type]) type = ""; + + // If zero fill is specified, padding goes after sign and before digits. + if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; + + this.fill = fill; + this.align = align; + this.sign = sign; + this.symbol = symbol; + this.zero = zero; + this.width = width; + this.comma = comma; + this.precision = precision; + this.type = type; } -function parseTypenames$1(typenames) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - return {type: t, name: name}; - }); -} +FormatSpecifier.prototype.toString = function() { + return this.fill + + this.align + + this.sign + + this.symbol + + (this.zero ? "0" : "") + + (this.width == null ? "" : Math.max(1, this.width | 0)) + + (this.comma ? "," : "") + + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) + + this.type; +}; -function onRemove(typename) { - return function() { - var on = this.__on; - if (!on) return; - for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { - if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.capture); - } else { - on[++i] = o; - } - } - if (++i) on.length = i; - else delete this.__on; - }; -} +var prefixes = ["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"]; -function onAdd(typename, value, capture) { - var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; - return function(d, i, group) { - var on = this.__on, o, listener = wrap(value, i, group); - if (on) for (var j = 0, m = on.length; j < m; ++j) { - if ((o = on[j]).type === typename.type && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.capture); - this.addEventListener(o.type, o.listener = listener, o.capture = capture); - o.value = value; - return; - } - } - this.addEventListener(typename.type, listener, capture); - o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; - if (!on) this.__on = [o]; - else on.push(o); - }; +function identity$3(x) { + return x; } -var selection_on = function(typename, value, capture) { - var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; +var formatLocale = function(locale) { + var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3, + currency = locale.currency, + decimal = locale.decimal; - if (arguments.length < 2) { - var on = this.node().__on; - if (on) for (var j = 0, m = on.length, o; j < m; ++j) { - for (i = 0, o = on[j]; i < n; ++i) { - if ((t = typenames[i]).type === o.type && t.name === o.name) { - return o.value; - } - } - } - return; - } + function newFormat(specifier) { + specifier = formatSpecifier(specifier); - on = value ? onAdd : onRemove; - if (capture == null) capture = false; - for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); - return this; -}; + var fill = specifier.fill, + align = specifier.align, + sign = specifier.sign, + symbol = specifier.symbol, + zero = specifier.zero, + width = specifier.width, + comma = specifier.comma, + precision = specifier.precision, + type = specifier.type; -function customEvent(event1, listener, that, args) { - var event0 = exports.event; - event1.sourceEvent = exports.event; - exports.event = event1; - try { - return listener.apply(that, args); - } finally { - exports.event = event0; - } -} + // Compute the prefix and suffix. + // For SI-prefix, the suffix is lazily computed. + var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", + suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : ""; -var sourceEvent = function() { - var current = exports.event, source; - while (source = current.sourceEvent) current = source; - return current; -}; + // What format function should we use? + // Is this an integer type? + // Can this type generate exponential notation? + var formatType = formatTypes[type], + maybeSuffix = !type || /[defgprs%]/.test(type); -var point$5 = function(node, event) { - var svg = node.ownerSVGElement || node; + // Set the default precision if not specified, + // or clamp the specified precision to the supported range. + // For significant precision, it must be in [1, 21]. + // For fixed precision, it must be in [0, 20]. + precision = precision == null ? (type ? 6 : 12) + : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) + : Math.max(0, Math.min(20, precision)); - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - point.x = event.clientX, point.y = event.clientY; - point = point.matrixTransform(node.getScreenCTM().inverse()); - return [point.x, point.y]; - } + function format(value) { + var valuePrefix = prefix, + valueSuffix = suffix, + i, n, c; - var rect = node.getBoundingClientRect(); - return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; -}; + if (type === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; -var mouse = function(node) { - var event = sourceEvent(); - if (event.changedTouches) event = event.changedTouches[0]; - return point$5(node, event); -}; + // Convert negative to positive, and compute the prefix. + // Note that -0 is not less than 0, but 1 / -0 is! + var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true); -function none$2() {} + // Perform the initial formatting. + value = formatType(value, precision); -var selector = function(selector) { - return selector == null ? none$2 : function() { - return this.querySelector(selector); - }; -}; + // If the original value was negative, it may be rounded to zero during + // formatting; treat this as (positive) zero. + if (valueNegative) { + i = -1, n = value.length; + valueNegative = false; + while (++i < n) { + if (c = value.charCodeAt(i), (48 < c && c < 58) + || (type === "x" && 96 < c && c < 103) + || (type === "X" && 64 < c && c < 71)) { + valueNegative = true; + break; + } + } + } -var selection_select = function(select) { - if (typeof select !== "function") select = selector(select); + // Compute the prefix and suffix. + valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; + // Break the formatted value into the integer “value” part that can be + // grouped, and fractional or exponential “suffix” part that is not. + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c = value.charCodeAt(i), 48 > c || c > 57) { + valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } } - } - } - - return new Selection(subgroups, this._parents); -}; -function empty() { - return []; -} + // If the fill character is not "0", grouping is applied before padding. + if (comma && !zero) value = group(value, Infinity); -var selectorAll = function(selector) { - return selector == null ? empty : function() { - return this.querySelectorAll(selector); - }; -}; + // Compute the padding. + var length = valuePrefix.length + value.length + valueSuffix.length, + padding = length < width ? new Array(width - length + 1).join(fill) : ""; -var selection_selectAll = function(select) { - if (typeof select !== "function") select = selectorAll(select); + // If the fill character is "0", grouping is applied after padding. + if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - subgroups.push(select.call(node, node.__data__, i, group)); - parents.push(node); + // Reconstruct the final output based on the desired alignment. + switch (align) { + case "<": return valuePrefix + value + valueSuffix + padding; + case "=": return valuePrefix + padding + value + valueSuffix; + case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); } + return padding + valuePrefix + value + valueSuffix; } + + format.toString = function() { + return specifier + ""; + }; + + return format; } - return new Selection(subgroups, parents); + function formatPrefix(specifier, value) { + var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), + e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3, + k = Math.pow(10, -e), + prefix = prefixes[8 + e / 3]; + return function(value) { + return f(k * value) + prefix; + }; + } + + return { + format: newFormat, + formatPrefix: formatPrefix + }; }; -var selection_filter = function(match) { - if (typeof match !== "function") match = matcher$1(match); +var locale$1; + + + +defaultLocale({ + decimal: ".", + thousands: ",", + grouping: [3], + currency: ["$", ""] +}); + +function defaultLocale(definition) { + locale$1 = formatLocale(definition); + exports.format = locale$1.format; + exports.formatPrefix = locale$1.formatPrefix; + return locale$1; +} - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } +var precisionFixed = function(step) { + return Math.max(0, -exponent$1(Math.abs(step))); +}; - return new Selection(subgroups, this._parents); +var precisionPrefix = function(step, value) { + return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step))); }; -var sparse = function(update) { - return new Array(update.length); +var precisionRound = function(step, max) { + step = Math.abs(step), max = Math.abs(max) - step; + return Math.max(0, exponent$1(max) - exponent$1(step)) + 1; }; -var selection_enter = function() { - return new Selection(this._enter || this._groups.map(sparse), this._parents); +// Adds floating point numbers with twice the normal precision. +// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and +// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) +// 305–363 (1997). +// Code adapted from GeographicLib by Charles F. F. Karney, +// http://geographiclib.sourceforge.net/ + +var adder = function() { + return new Adder; }; -function EnterNode(parent, datum) { - this.ownerDocument = parent.ownerDocument; - this.namespaceURI = parent.namespaceURI; - this._next = null; - this._parent = parent; - this.__data__ = datum; +function Adder() { + this.reset(); } -EnterNode.prototype = { - constructor: EnterNode, - appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, - insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, - querySelector: function(selector) { return this._parent.querySelector(selector); }, - querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } +Adder.prototype = { + constructor: Adder, + reset: function() { + this.s = // rounded value + this.t = 0; // exact error + }, + add: function(y) { + add$1(temp, y, this.t); + add$1(this, temp.s, this.s); + if (this.s) this.t += temp.t; + else this.s = temp.t; + }, + valueOf: function() { + return this.s; + } }; -var constant$5 = function(x) { - return function() { - return x; - }; -}; +var temp = new Adder; -var keyPrefix = "$"; // Protect against keys like “__proto__”. +function add$1(adder, a, b) { + var x = adder.s = a + b, + bv = x - a, + av = x - bv; + adder.t = (a - av) + (b - bv); +} -function bindIndex(parent, group, enter, update, exit, data) { - var i = 0, - node, - groupLength = group.length, - dataLength = data.length; +var epsilon$2 = 1e-6; +var epsilon2$1 = 1e-12; +var pi$3 = Math.PI; +var halfPi$2 = pi$3 / 2; +var quarterPi = pi$3 / 4; +var tau$3 = pi$3 * 2; - // Put any non-null nodes that fit into update. - // Put any null nodes into enter. - // Put any remaining data into enter. - for (; i < dataLength; ++i) { - if (node = group[i]) { - node.__data__ = data[i]; - update[i] = node; - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } +var degrees$1 = 180 / pi$3; +var radians = pi$3 / 180; - // Put any non-null nodes that don’t fit into exit. - for (; i < groupLength; ++i) { - if (node = group[i]) { - exit[i] = node; - } - } +var abs = Math.abs; +var atan = Math.atan; +var atan2 = Math.atan2; +var cos$1 = Math.cos; +var ceil = Math.ceil; +var exp = Math.exp; + +var log = Math.log; +var pow = Math.pow; +var sin$1 = Math.sin; +var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; +var sqrt = Math.sqrt; +var tan = Math.tan; + +function acos(x) { + return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x); } -function bindKey(parent, group, enter, update, exit, data, key) { - var i, - node, - nodeByKeyValue = {}, - groupLength = group.length, - dataLength = data.length, - keyValues = new Array(groupLength), - keyValue; +function asin(x) { + return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x); +} - // Compute the key for each node. - // If multiple nodes have the same key, the duplicates are added to exit. - for (i = 0; i < groupLength; ++i) { - if (node = group[i]) { - keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); - if (keyValue in nodeByKeyValue) { - exit[i] = node; - } else { - nodeByKeyValue[keyValue] = node; - } - } - } +function haversin(x) { + return (x = sin$1(x / 2)) * x; +} - // Compute the key for each datum. - // If there a node associated with this key, join and add it to update. - // If there is not (or the key is a duplicate), add it to enter. - for (i = 0; i < dataLength; ++i) { - keyValue = keyPrefix + key.call(parent, data[i], i, data); - if (node = nodeByKeyValue[keyValue]) { - update[i] = node; - node.__data__ = data[i]; - nodeByKeyValue[keyValue] = null; - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } +function noop$1() {} - // Add any remaining nodes that were not bound to data to exit. - for (i = 0; i < groupLength; ++i) { - if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { - exit[i] = node; - } +function streamGeometry(geometry, stream) { + if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { + streamGeometryType[geometry.type](geometry, stream); } } -var selection_data = function(value, key) { - if (!value) { - data = new Array(this.size()), j = -1; - this.each(function(d) { data[++j] = d; }); - return data; +var streamObjectType = { + Feature: function(feature, stream) { + streamGeometry(feature.geometry, stream); + }, + FeatureCollection: function(object, stream) { + var features = object.features, i = -1, n = features.length; + while (++i < n) streamGeometry(features[i].geometry, stream); } +}; - var bind = key ? bindKey : bindIndex, - parents = this._parents, - groups = this._groups; - - if (typeof value !== "function") value = constant$5(value); - - for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { - var parent = parents[j], - group = groups[j], - groupLength = group.length, - data = value.call(parent, parent && parent.__data__, j, parents), - dataLength = data.length, - enterGroup = enter[j] = new Array(dataLength), - updateGroup = update[j] = new Array(dataLength), - exitGroup = exit[j] = new Array(groupLength); - - bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); - - // Now connect the enter nodes to their following update node, such that - // appendChild can insert the materialized enter node before this node, - // rather than at the end of the parent node. - for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { - if (previous = enterGroup[i0]) { - if (i0 >= i1) i1 = i0 + 1; - while (!(next = updateGroup[i1]) && ++i1 < dataLength); - previous._next = next || null; - } - } +var streamGeometryType = { + Sphere: function(object, stream) { + stream.sphere(); + }, + Point: function(object, stream) { + object = object.coordinates; + stream.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); + }, + LineString: function(object, stream) { + streamLine(object.coordinates, stream, 0); + }, + MultiLineString: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamLine(coordinates[i], stream, 0); + }, + Polygon: function(object, stream) { + streamPolygon(object.coordinates, stream); + }, + MultiPolygon: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamPolygon(coordinates[i], stream); + }, + GeometryCollection: function(object, stream) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) streamGeometry(geometries[i], stream); } - - update = new Selection(update, parents); - update._enter = enter; - update._exit = exit; - return update; }; -var selection_exit = function() { - return new Selection(this._exit || this._groups.map(sparse), this._parents); -}; +function streamLine(coordinates, stream, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + stream.lineStart(); + while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); + stream.lineEnd(); +} -var selection_merge = function(selection) { +function streamPolygon(coordinates, stream) { + var i = -1, n = coordinates.length; + stream.polygonStart(); + while (++i < n) streamLine(coordinates[i], stream, 1); + stream.polygonEnd(); +} - for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } +var geoStream = function(object, stream) { + if (object && streamObjectType.hasOwnProperty(object.type)) { + streamObjectType[object.type](object, stream); + } else { + streamGeometry(object, stream); } +}; - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } +var areaRingSum = adder(); - return new Selection(merges, this._parents); +var areaSum = adder(); +var lambda00; +var phi00; +var lambda0; +var cosPhi0; +var sinPhi0; + +var areaStream = { + point: noop$1, + lineStart: noop$1, + lineEnd: noop$1, + polygonStart: function() { + areaRingSum.reset(); + areaStream.lineStart = areaRingStart; + areaStream.lineEnd = areaRingEnd; + }, + polygonEnd: function() { + var areaRing = +areaRingSum; + areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing); + this.lineStart = this.lineEnd = this.point = noop$1; + }, + sphere: function() { + areaSum.add(tau$3); + } }; -var selection_order = function() { +function areaRingStart() { + areaStream.point = areaPointFirst; +} - for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { - for (var group = groups[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; - } - } - } +function areaRingEnd() { + areaPoint(lambda00, phi00); +} - return this; -}; +function areaPointFirst(lambda, phi) { + areaStream.point = areaPoint; + lambda00 = lambda, phi00 = phi; + lambda *= radians, phi *= radians; + lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi); +} -var selection_sort = function(compare) { - if (!compare) compare = ascending$2; +function areaPoint(lambda, phi) { + lambda *= radians, phi *= radians; + phi = phi / 2 + quarterPi; // half the angular distance from south pole - function compareNode(a, b) { - return a && b ? compare(a.__data__, b.__data__) : !a - !b; - } + // Spherical excess E for a spherical triangle with vertices: south pole, + // previous point, current point. Uses a formula derived from Cagnoli’s + // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). + var dLambda = lambda - lambda0, + sdLambda = dLambda >= 0 ? 1 : -1, + adLambda = sdLambda * dLambda, + cosPhi = cos$1(phi), + sinPhi = sin$1(phi), + k = sinPhi0 * sinPhi, + u = cosPhi0 * cosPhi + k * cos$1(adLambda), + v = k * sdLambda * sin$1(adLambda); + areaRingSum.add(atan2(v, u)); - for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group[i]) { - sortgroup[i] = node; - } - } - sortgroup.sort(compareNode); - } + // Advance the previous points. + lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; +} - return new Selection(sortgroups, this._parents).order(); +var area = function(object) { + areaSum.reset(); + geoStream(object, areaStream); + return areaSum * 2; }; -function ascending$2(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +function spherical(cartesian) { + return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; } -var selection_call = function() { - var callback = arguments[0]; - arguments[0] = this; - callback.apply(null, arguments); - return this; -}; +function cartesian(spherical) { + var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi); + return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)]; +} -var selection_nodes = function() { - var nodes = new Array(this.size()), i = -1; - this.each(function() { nodes[++i] = this; }); - return nodes; -}; +function cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} -var selection_node = function() { +function 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]]; +} - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { - var node = group[i]; - if (node) return node; - } - } +// TODO return a +function cartesianAddInPlace(a, b) { + a[0] += b[0], a[1] += b[1], a[2] += b[2]; +} - return null; -}; +function cartesianScale(vector, k) { + return [vector[0] * k, vector[1] * k, vector[2] * k]; +} -var selection_size = function() { - var size = 0; - this.each(function() { ++size; }); - return size; -}; +// TODO return d +function cartesianNormalizeInPlace(d) { + var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l, d[1] /= l, d[2] /= l; +} -var selection_empty = function() { - return !this.node(); +var lambda0$1; +var phi0; +var lambda1; +var phi1; +var lambda2; +var lambda00$1; +var phi00$1; +var p0; +var deltaSum = adder(); +var ranges; +var range; + +var boundsStream = { + point: boundsPoint, + lineStart: boundsLineStart, + lineEnd: boundsLineEnd, + polygonStart: function() { + boundsStream.point = boundsRingPoint; + boundsStream.lineStart = boundsRingStart; + boundsStream.lineEnd = boundsRingEnd; + deltaSum.reset(); + areaStream.polygonStart(); + }, + polygonEnd: function() { + areaStream.polygonEnd(); + boundsStream.point = boundsPoint; + boundsStream.lineStart = boundsLineStart; + boundsStream.lineEnd = boundsLineEnd; + if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); + else if (deltaSum > epsilon$2) phi1 = 90; + else if (deltaSum < -epsilon$2) phi0 = -90; + range[0] = lambda0$1, range[1] = lambda1; + } }; -var selection_each = function(callback) { +function boundsPoint(lambda, phi) { + ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]); + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; +} - for (var groups = this._groups, 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.call(node, node.__data__, i, group); +function linePoint(lambda, phi) { + var p = cartesian([lambda * radians, phi * radians]); + if (p0) { + var normal = cartesianCross(p0, p), + equatorial = [normal[1], -normal[0], 0], + inflection = cartesianCross(equatorial, normal); + cartesianNormalizeInPlace(inflection); + inflection = spherical(inflection); + var delta = lambda - lambda2, + sign$$1 = delta > 0 ? 1 : -1, + lambdai = inflection[0] * degrees$1 * sign$$1, + phii, + antimeridian = abs(delta) > 180; + if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = inflection[1] * degrees$1; + if (phii > phi1) phi1 = phii; + } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = -inflection[1] * degrees$1; + if (phii < phi0) phi0 = phii; + } else { + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; + } + if (antimeridian) { + if (lambda < lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } else { + if (lambda1 >= lambda0$1) { + if (lambda < lambda0$1) lambda0$1 = lambda; + if (lambda > lambda1) lambda1 = lambda; + } else { + if (lambda > lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } } + } else { + boundsPoint(lambda, phi); } + p0 = p, lambda2 = lambda; +} - return this; -}; +function boundsLineStart() { + boundsStream.point = linePoint; +} -function attrRemove(name) { - return function() { - this.removeAttribute(name); - }; +function boundsLineEnd() { + range[0] = lambda0$1, range[1] = lambda1; + boundsStream.point = boundsPoint; + p0 = null; } -function attrRemoveNS(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); - }; +function boundsRingPoint(lambda, phi) { + if (p0) { + var delta = lambda - lambda2; + deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); + } else { + lambda00$1 = lambda, phi00$1 = phi; + } + areaStream.point(lambda, phi); + linePoint(lambda, phi); } -function attrConstant(name, value) { - return function() { - this.setAttribute(name, value); - }; +function boundsRingStart() { + areaStream.lineStart(); +} + +function boundsRingEnd() { + boundsRingPoint(lambda00$1, phi00$1); + areaStream.lineEnd(); + if (abs(deltaSum) > epsilon$2) lambda0$1 = -(lambda1 = 180); + range[0] = lambda0$1, range[1] = lambda1; + p0 = null; +} + +// Finds the left-right distance between two longitudes. +// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want +// the distance between ±180° to be 360°. +function angle(lambda0, lambda1) { + return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; } -function attrConstantNS(fullname, value) { - return function() { - this.setAttributeNS(fullname.space, fullname.local, value); - }; +function rangeCompare(a, b) { + return a[0] - b[0]; } -function attrFunction(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttribute(name); - else this.setAttribute(name, v); - }; +function rangeContains(range, x) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; } -function attrFunctionNS(fullname, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttributeNS(fullname.space, fullname.local); - else this.setAttributeNS(fullname.space, fullname.local, v); - }; -} +var bounds = function(feature) { + var i, n, a, b, merged, deltaMax, delta; -var selection_attr = function(name, value) { - var fullname = namespace(name); + phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); + ranges = []; + geoStream(feature, boundsStream); - if (arguments.length < 2) { - var node = this.node(); - return fullname.local - ? node.getAttributeNS(fullname.space, fullname.local) - : node.getAttribute(fullname); + // First, sort ranges by their minimum longitudes. + if (n = ranges.length) { + ranges.sort(rangeCompare); + + // Then, merge any ranges that overlap. + for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { + b = ranges[i]; + if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { + 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); + } + } + + // Finally, find the largest gap between the merged ranges. + // The final bounding box will be the inverse of this gap. + for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { + b = merged[i]; + if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; + } } - return this.each((value == null - ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" - ? (fullname.local ? attrFunctionNS : attrFunction) - : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); + ranges = range = null; + + return lambda0$1 === Infinity || phi0 === Infinity + ? [[NaN, NaN], [NaN, NaN]] + : [[lambda0$1, phi0], [lambda1, phi1]]; }; -var window = function(node) { - return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node - || (node.document && node) // node is a Window - || node.defaultView; // node is a Document +var W0; +var W1; +var X0; +var Y0; +var Z0; +var X1; +var Y1; +var Z1; +var X2; +var Y2; +var Z2; +var lambda00$2; +var phi00$2; +var x0; +var y0; +var z0; // previous point + +var centroidStream = { + sphere: noop$1, + point: centroidPoint, + lineStart: centroidLineStart, + lineEnd: centroidLineEnd, + polygonStart: function() { + centroidStream.lineStart = centroidRingStart; + centroidStream.lineEnd = centroidRingEnd; + }, + polygonEnd: function() { + centroidStream.lineStart = centroidLineStart; + centroidStream.lineEnd = centroidLineEnd; + } }; -function styleRemove(name) { - return function() { - this.style.removeProperty(name); - }; +// Arithmetic mean of Cartesian vectors. +function centroidPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)); } -function styleConstant(name, value, priority) { - return function() { - this.style.setProperty(name, value, priority); - }; +function centroidPointCartesian(x, y, z) { + ++W0; + X0 += (x - X0) / W0; + Y0 += (y - Y0) / W0; + Z0 += (z - Z0) / W0; } -function styleFunction(name, value, priority) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.style.removeProperty(name); - else this.style.setProperty(name, v, priority); - }; +function centroidLineStart() { + centroidStream.point = centroidLinePointFirst; } -var selection_style = function(name, value, priority) { - var node; - return arguments.length > 1 - ? this.each((value == null - ? styleRemove : typeof value === "function" - ? styleFunction - : styleConstant)(name, value, priority == null ? "" : priority)) - : window(node = this.node()) - .getComputedStyle(node, null) - .getPropertyValue(name); -}; - -function propertyRemove(name) { - return function() { - delete this[name]; - }; +function centroidLinePointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidStream.point = centroidLinePoint; + centroidPointCartesian(x0, y0, z0); } -function propertyConstant(name, value) { - return function() { - this[name] = value; - }; +function centroidLinePoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + w = atan2(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); + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); } -function propertyFunction(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) delete this[name]; - else this[name] = v; - }; +function centroidLineEnd() { + centroidStream.point = centroidPoint; } -var selection_property = function(name, value) { - return arguments.length > 1 - ? this.each((value == null - ? propertyRemove : typeof value === "function" - ? propertyFunction - : propertyConstant)(name, value)) - : this.node()[name]; -}; +// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, +// J. Applied Mechanics 42, 239 (1975). +function centroidRingStart() { + centroidStream.point = centroidRingPointFirst; +} -function classArray(string) { - return string.trim().split(/^|\s+/); +function centroidRingEnd() { + centroidRingPoint(lambda00$2, phi00$2); + centroidStream.point = centroidPoint; } -function classList(node) { - return node.classList || new ClassList(node); +function centroidRingPointFirst(lambda, phi) { + lambda00$2 = lambda, phi00$2 = phi; + lambda *= radians, phi *= radians; + centroidStream.point = centroidRingPoint; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidPointCartesian(x0, y0, z0); } -function ClassList(node) { - this._node = node; - this._names = classArray(node.getAttribute("class") || ""); +function centroidRingPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + cx = y0 * z - z0 * y, + cy = z0 * x - x0 * z, + cz = x0 * y - y0 * x, + m = sqrt(cx * cx + cy * cy + cz * cz), + u = x0 * x + y0 * y + z0 * z, + v = m && -acos(u) / m, // area weight + w = atan2(m, u); // line weight + X2 += v * cx; + Y2 += v * cy; + Z2 += v * cz; + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); } -ClassList.prototype = { - add: function(name) { - var i = this._names.indexOf(name); - if (i < 0) { - this._names.push(name); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - remove: function(name) { - var i = this._names.indexOf(name); - if (i >= 0) { - this._names.splice(i, 1); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - contains: function(name) { - return this._names.indexOf(name) >= 0; +var centroid = function(object) { + W0 = W1 = + X0 = Y0 = Z0 = + X1 = Y1 = Z1 = + X2 = Y2 = Z2 = 0; + geoStream(object, centroidStream); + + var x = X2, + y = Y2, + z = Z2, + m = x * x + y * y + z * z; + + // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. + if (m < epsilon2$1) { + x = X1, y = Y1, z = Z1; + // If the feature has zero length, fall back to arithmetic mean of point vectors. + if (W1 < epsilon$2) x = X0, y = Y0, z = Z0; + m = x * x + y * y + z * z; + // If the feature still has an undefined ccentroid, then return. + if (m < epsilon2$1) return [NaN, NaN]; } -}; - -function classedAdd(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.add(names[i]); -} -function classedRemove(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.remove(names[i]); -} + return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1]; +}; -function classedTrue(names) { +var constant$7 = function(x) { return function() { - classedAdd(this, names); + return x; }; -} +}; -function classedFalse(names) { - return function() { - classedRemove(this, names); - }; -} +var compose = function(a, b) { -function classedFunction(names, value) { - return function() { - (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); }; -} -var selection_classed = function(name, value) { - var names = classArray(name + ""); + return compose; +}; - if (arguments.length < 2) { - var list = classList(this.node()), i = -1, n = names.length; - while (++i < n) if (!list.contains(names[i])) return false; - return true; - } +function rotationIdentity(lambda, phi) { + return [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi]; +} - return this.each((typeof value === "function" - ? classedFunction : value - ? classedTrue - : classedFalse)(names, value)); -}; +rotationIdentity.invert = rotationIdentity; -function textRemove() { - this.textContent = ""; +function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { + return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) + : rotationLambda(deltaLambda)) + : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) + : rotationIdentity); } -function textConstant(value) { - return function() { - this.textContent = value; +function forwardRotationLambda(deltaLambda) { + return function(lambda, phi) { + return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi]; }; } -function textFunction(value) { - return function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - }; +function rotationLambda(deltaLambda) { + var rotation = forwardRotationLambda(deltaLambda); + rotation.invert = forwardRotationLambda(-deltaLambda); + return rotation; } -var selection_text = function(value) { - return arguments.length - ? this.each(value == null - ? textRemove : (typeof value === "function" - ? textFunction - : textConstant)(value)) - : this.node().textContent; -}; +function rotationPhiGamma(deltaPhi, deltaGamma) { + var cosDeltaPhi = cos$1(deltaPhi), + sinDeltaPhi = sin$1(deltaPhi), + cosDeltaGamma = cos$1(deltaGamma), + sinDeltaGamma = sin$1(deltaGamma); -function htmlRemove() { - this.innerHTML = ""; -} + function rotation(lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaPhi + x * sinDeltaPhi; + return [ + atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), + asin(k * cosDeltaGamma + y * sinDeltaGamma) + ]; + } -function htmlConstant(value) { - return function() { - this.innerHTML = value; + rotation.invert = function(lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaGamma - y * sinDeltaGamma; + return [ + atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), + asin(k * cosDeltaPhi - x * sinDeltaPhi) + ]; }; + + return rotation; } -function htmlFunction(value) { - return function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; +var rotation = function(rotate) { + rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); + + function forward(coordinates) { + coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + } + + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; }; -} -var selection_html = function(value) { - return arguments.length - ? this.each(value == null - ? htmlRemove : (typeof value === "function" - ? htmlFunction - : htmlConstant)(value)) - : this.node().innerHTML; + return forward; }; -function raise$1() { - if (this.nextSibling) this.parentNode.appendChild(this); +// Generates a circle centered at [0°, 0°], with a given radius and precision. +function circleStream(stream, radius, delta, direction, t0, t1) { + if (!delta) return; + var cosRadius = cos$1(radius), + sinRadius = sin$1(radius), + step = direction * delta; + if (t0 == null) { + t0 = radius + direction * tau$3; + t1 = radius - step / 2; + } else { + t0 = circleRadius(cosRadius, t0); + t1 = circleRadius(cosRadius, t1); + if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$3; + } + for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { + point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]); + stream.point(point[0], point[1]); + } } -var selection_raise = function() { - return this.each(raise$1); -}; - -function lower() { - if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); +// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. +function circleRadius(cosRadius, point) { + point = cartesian(point), point[0] -= cosRadius; + cartesianNormalizeInPlace(point); + var radius = acos(-point[1]); + return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3; } -var selection_lower = function() { - return this.each(lower); -}; +var circle = function() { + var center = constant$7([0, 0]), + radius = constant$7(90), + precision = constant$7(6), + ring, + rotate, + stream = {point: point}; -var selection_append = function(name) { - var create = typeof name === "function" ? name : creator(name); - return this.select(function() { - return this.appendChild(create.apply(this, arguments)); - }); -}; + function point(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= degrees$1, x[1] *= degrees$1; + } -function constantNull() { - return null; -} + function circle() { + var c = center.apply(this, arguments), + r = radius.apply(this, arguments) * radians, + p = precision.apply(this, arguments) * radians; + ring = []; + rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; + circleStream(stream, r, p, 1); + c = {type: "Polygon", coordinates: [ring]}; + ring = rotate = null; + return c; + } -var selection_insert = function(name, before) { - var create = typeof name === "function" ? name : creator(name), - select = before == null ? constantNull : typeof before === "function" ? before : selector(before); - return this.select(function() { - return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); - }); -}; + circle.center = function(_) { + return arguments.length ? (center = typeof _ === "function" ? _ : constant$7([+_[0], +_[1]]), circle) : center; + }; -function remove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); -} + circle.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), circle) : radius; + }; -var selection_remove = function() { - return this.each(remove); + circle.precision = function(_) { + return arguments.length ? (precision = typeof _ === "function" ? _ : constant$7(+_), circle) : precision; + }; + + return circle; }; -var selection_datum = function(value) { - return arguments.length - ? this.property("__data__", value) - : this.node().__data__; +var clipBuffer = function() { + var lines = [], + line; + return { + point: function(x, y) { + line.push([x, y]); + }, + lineStart: function() { + lines.push(line = []); + }, + lineEnd: noop$1, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + }, + result: function() { + var result = lines; + lines = []; + line = null; + return result; + } + }; }; -function dispatchEvent(node, type, params) { - var window$$1 = window(node), - event = window$$1.CustomEvent; +var clipLine = function(a, b, x0, y0, x1, y1) { + var ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; - if (event) { - event = new event(type, params); - } else { - event = window$$1.document.createEvent("Event"); - if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; - else event.initEvent(type, false, false); + 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; } - node.dispatchEvent(event); -} + 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; + } -function dispatchConstant(type, params) { - return function() { - return dispatchEvent(this, type, params); - }; -} + 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 dispatchFunction(type, params) { - return function() { - return dispatchEvent(this, type, params.apply(this, arguments)); - }; -} + 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; + } -var selection_dispatch = function(type, params) { - return this.each((typeof params === "function" - ? dispatchFunction - : dispatchConstant)(type, params)); + if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; + if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; + return true; }; -var root = [null]; +var pointEqual = function(a, b) { + return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2; +}; -function Selection(groups, parents) { - this._groups = groups; - this._parents = parents; +function Intersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; // another intersection + this.e = entry; // is an entry? + this.v = false; // visited + this.n = this.p = null; // next & previous } -function selection() { - return new Selection([[document.documentElement]], root); -} +// A generalized polygon clipping algorithm: given a polygon that has been cut +// into its visible line segments, and rejoins the segments by interpolating +// along the clip edge. +var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) { + var subject = [], + clip = [], + i, + n; -Selection.prototype = selection.prototype = { - constructor: Selection, - select: selection_select, - selectAll: selection_selectAll, - filter: selection_filter, - data: selection_data, - enter: selection_enter, - exit: selection_exit, - merge: selection_merge, - order: selection_order, - sort: selection_sort, - call: selection_call, - nodes: selection_nodes, - node: selection_node, - size: selection_size, - empty: selection_empty, - each: selection_each, - attr: selection_attr, - style: selection_style, - property: selection_property, - classed: selection_classed, - text: selection_text, - html: selection_html, - raise: selection_raise, - lower: selection_lower, - append: selection_append, - insert: selection_insert, - remove: selection_remove, - datum: selection_datum, - on: selection_on, - dispatch: selection_dispatch -}; + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n], x; -var select = function(selector) { - return typeof selector === "string" - ? new Selection([[document.querySelector(selector)]], [document.documentElement]) - : new Selection([[selector]], root); -}; + // If the first and last points of a segment are coincident, then treat as a + // closed ring. TODO if all rings are closed, then the winding order of the + // exterior ring should be checked. + if (pointEqual(p0, p1)) { + stream.lineStart(); + for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); + stream.lineEnd(); + return; + } -var selectAll = function(selector) { - return typeof selector === "string" - ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) - : new Selection([selector == null ? [] : selector], root); -}; + subject.push(x = new Intersection(p0, segment, null, true)); + clip.push(x.o = new Intersection(p0, null, x, false)); + subject.push(x = new Intersection(p1, segment, null, false)); + clip.push(x.o = new Intersection(p1, null, x, true)); + }); -var touch = function(node, touches, identifier) { - if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; + if (!subject.length) return; - for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { - if ((touch = touches[i]).identifier === identifier) { - return point$5(node, touch); - } - } + clip.sort(compareIntersection); + link$1(subject); + link$1(clip); - return null; -}; + for (i = 0, n = clip.length; i < n; ++i) { + clip[i].e = startInside = !startInside; + } -var touches = function(node, touches) { - if (touches == null) touches = sourceEvent().touches; + var start = subject[0], + points, + point; - for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { - points[i] = point$5(node, touches[i]); + while (1) { + // Find first unvisited intersection. + var current = start, + isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + stream.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, stream); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, stream); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + stream.lineEnd(); } - - return points; }; -var emptyOn = dispatch("start", "end", "interrupt"); -var emptyTween = []; - -var CREATED = 0; -var SCHEDULED = 1; -var STARTING = 2; -var STARTED = 3; -var RUNNING = 4; -var ENDING = 5; -var ENDED = 6; +function link$1(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; +} -var schedule = function(node, name, id, index, group, timing) { - var schedules = node.__transition; - if (!schedules) node.__transition = {}; - else if (id in schedules) return; - create(node, id, { - name: name, - index: index, // For context during callback. - group: group, // For context during callback. - on: emptyOn, - tween: emptyTween, - time: timing.time, - delay: timing.delay, - duration: timing.duration, - ease: timing.ease, - timer: null, - state: CREATED - }); -}; +var clipMax = 1e9; +var clipMin = -clipMax; -function init(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late"); - return schedule; -} +// TODO Use d3-polygon’s polygonContains here for the ring check? +// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? -function set$3(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); - return schedule; -} +function clipExtent(x0, y0, x1, y1) { -function get$1(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id])) throw new Error("too late"); - return schedule; -} + function visible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } -function create(node, id, self) { - var schedules = node.__transition, - tween; + function interpolate(from, to, direction, stream) { + var a = 0, a1 = 0; + if (from == null + || (a = corner(from, direction)) !== (a1 = corner(to, direction)) + || comparePoint(from, to) < 0 ^ direction > 0) { + do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + while ((a = (a + direction + 4) % 4) !== a1); + } else { + stream.point(to[0], to[1]); + } + } - // Initialize the self timer when the transition is created. - // Note the actual delay is not known until the first callback! - schedules[id] = self; - self.timer = timer(schedule, 0, self.time); + function corner(p, direction) { + return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3 + : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1 + : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0 + : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon + } - function schedule(elapsed) { - self.state = SCHEDULED; - self.timer.restart(start, self.delay, self.time); + function compareIntersection(a, b) { + return comparePoint(a.x, b.x); + } - // If the elapsed delay is less than our first sleep, start immediately. - if (self.delay <= elapsed) start(elapsed - self.delay); + function comparePoint(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 start(elapsed) { - var i, j, n, o; + return function(stream) { + var activeStream = stream, + bufferStream = clipBuffer(), + segments, + polygon, + ring, + x__, y__, v__, // first point + x_, y_, v_, // previous point + first, + clean; - // If the state is not SCHEDULED, then we previously errored on start. - if (self.state !== SCHEDULED) return stop(); + var clipStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: polygonStart, + polygonEnd: polygonEnd + }; - for (i in schedules) { - o = schedules[i]; - if (o.name !== self.name) continue; + function point(x, y) { + if (visible(x, y)) activeStream.point(x, y); + } - // While this element already has a starting transition during this frame, - // defer starting an interrupting transition until that transition has a - // chance to tick (and possibly end); see d3/d3-transition#54! - if (o.state === STARTED) return timeout$1(start); + function polygonInside() { + var winding = 0; - // Interrupt the active transition, if any. - // Dispatch the interrupt event. - if (o.state === RUNNING) { - o.state = ENDED; - o.timer.stop(); - o.on.call("interrupt", node, node.__data__, o.index, o.group); - delete schedules[i]; + for (var i = 0, n = polygon.length; i < n; ++i) { + for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { + a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; + if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } + else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } + } } - // Cancel any pre-empted transitions. No interrupt event is dispatched - // because the cancelled transitions never started. Note that this also - // removes this transition from the pending list! - else if (+i < id) { - o.state = ENDED; - o.timer.stop(); - delete schedules[i]; - } + return winding; } - // Defer the first tick to end of the current frame; see d3/d3#1576. - // Note the transition may be canceled after start and before the first tick! - // Note this must be scheduled before the start event; see d3/d3-transition#16! - // Assuming this is successful, subsequent callbacks go straight to tick. - timeout$1(function() { - if (self.state === STARTED) { - self.state = RUNNING; - self.timer.restart(tick, self.delay, self.time); - tick(elapsed); - } - }); - - // Dispatch the start event. - // Note this must be done before the tween are initialized. - self.state = STARTING; - self.on.call("start", node, node.__data__, self.index, self.group); - if (self.state !== STARTING) return; // interrupted - self.state = STARTED; + // Buffer geometry within a polygon and then clip it en masse. + function polygonStart() { + activeStream = bufferStream, segments = [], polygon = [], clean = true; + } - // Initialize the tween, deleting null tween. - tween = new Array(n = self.tween.length); - for (i = 0, j = -1; i < n; ++i) { - if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { - tween[++j] = o; + function polygonEnd() { + var startInside = polygonInside(), + cleanInside = clean && startInside, + visible = (segments = merge(segments)).length; + if (cleanInside || visible) { + stream.polygonStart(); + if (cleanInside) { + stream.lineStart(); + interpolate(null, null, 1, stream); + stream.lineEnd(); + } + if (visible) { + clipPolygon(segments, compareIntersection, startInside, interpolate, stream); + } + stream.polygonEnd(); } + activeStream = stream, segments = polygon = ring = null; } - tween.length = j + 1; - } - function tick(elapsed) { - var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), - i = -1, - n = tween.length; + function lineStart() { + clipStream.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } - while (++i < n) { - tween[i].call(null, t); + // TODO rather than special-case polygons, simply handle them separately. + // Ideally, coincident intersection points should be jittered to avoid + // clipping issues. + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferStream.rejoin(); + segments.push(bufferStream.result()); + } + clipStream.point = point; + if (v_) activeStream.lineEnd(); } - // Dispatch the end event. - if (self.state === ENDING) { - self.on.call("end", node, node.__data__, self.index, self.group); - stop(); + function linePoint(x, y) { + var v = visible(x, y); + if (polygon) ring.push([x, y]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + } + } else { + if (v && v_) activeStream.point(x, y); + else { + var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], + b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; + if (clipLine(a, b, x0, y0, x1, y1)) { + if (!v_) { + activeStream.lineStart(); + activeStream.point(a[0], a[1]); + } + activeStream.point(b[0], b[1]); + if (!v) activeStream.lineEnd(); + clean = false; + } else if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; } - } - function stop() { - self.state = ENDED; - self.timer.stop(); - delete schedules[id]; - for (var i in schedules) return; // eslint-disable-line no-unused-vars - delete node.__transition; - } + return clipStream; + }; } -var interrupt = function(node, name) { - var schedules = node.__transition, - schedule, - active, - empty = true, - i; +var extent$1 = function() { + var x0 = 0, + y0 = 0, + x1 = 960, + y1 = 500, + cache, + cacheStream, + clip; - if (!schedules) return; + return clip = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream); + }, + extent: function(_) { + return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; + } + }; +}; - name = name == null ? null : name + ""; +var lengthSum = adder(); +var lambda0$2; +var sinPhi0$1; +var cosPhi0$1; - for (i in schedules) { - if ((schedule = schedules[i]).name !== name) { empty = false; continue; } - active = schedule.state > STARTING && schedule.state < ENDING; - schedule.state = ENDED; - schedule.timer.stop(); - if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group); - delete schedules[i]; - } +var lengthStream = { + sphere: noop$1, + point: noop$1, + lineStart: lengthLineStart, + lineEnd: noop$1, + polygonStart: noop$1, + polygonEnd: noop$1 +}; + +function lengthLineStart() { + lengthStream.point = lengthPointFirst; + lengthStream.lineEnd = lengthLineEnd; +} + +function lengthLineEnd() { + lengthStream.point = lengthStream.lineEnd = noop$1; +} + +function lengthPointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi); + lengthStream.point = lengthPoint; +} - if (empty) delete node.__transition; -}; +function lengthPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var sinPhi = sin$1(phi), + cosPhi = cos$1(phi), + delta = abs(lambda - lambda0$2), + cosDelta = cos$1(delta), + sinDelta = sin$1(delta), + x = cosPhi * sinDelta, + y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, + z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; + lengthSum.add(atan2(sqrt(x * x + y * y), z)); + lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; +} -var selection_interrupt = function(name) { - return this.each(function() { - interrupt(this, name); - }); +var length$1 = function(object) { + lengthSum.reset(); + geoStream(object, lengthStream); + return +lengthSum; }; -function tweenRemove(id, name) { - var tween0, tween1; - return function() { - var schedule = set$3(this, id), - tween = schedule.tween; +var coordinates = [null, null]; +var object$1 = {type: "LineString", coordinates: coordinates}; - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = tween0 = tween; - for (var i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1 = tween1.slice(); - tween1.splice(i, 1); - break; - } - } - } +var distance = function(a, b) { + coordinates[0] = a; + coordinates[1] = b; + return length$1(object$1); +}; - schedule.tween = tween1; - }; +function graticuleX(y0, y1, dy) { + var y = sequence(y0, y1 - epsilon$2, dy).concat(y1); + return function(x) { return y.map(function(y) { return [x, y]; }); }; } -function tweenFunction(id, name, value) { - var tween0, tween1; - if (typeof value !== "function") throw new Error; - return function() { - var schedule = set$3(this, id), - tween = schedule.tween; - - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = (tween0 = tween).slice(); - for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1[i] = t; - break; - } - } - if (i === n) tween1.push(t); - } - - schedule.tween = tween1; - }; +function graticuleY(x0, x1, dx) { + var x = sequence(x0, x1 - epsilon$2, dx).concat(x1); + return function(y) { return x.map(function(x) { return [x, y]; }); }; } -var transition_tween = function(name, value) { - var id = this._id; +function graticule() { + var x1, x0, X1, X0, + y1, y0, Y1, Y0, + dx = 10, dy = dx, DX = 90, DY = 360, + x, y, X, Y, + precision = 2.5; - name += ""; + function graticule() { + return {type: "MultiLineString", coordinates: lines()}; + } - if (arguments.length < 2) { - var tween = get$1(this.node(), id).tween; - for (var i = 0, n = tween.length, t; i < n; ++i) { - if ((t = tween[i]).name === name) { - return t.value; - } - } - return null; + function lines() { + return sequence(ceil(X0 / DX) * DX, X1, DX).map(X) + .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) + .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$2; }).map(x)) + .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$2; }).map(y)); } - return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); -}; + graticule.lines = function() { + return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; }); + }; -function tweenValue(transition, name, value) { - var id = transition._id; + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ + X(X0).concat( + Y(Y1).slice(1), + X(X1).reverse().slice(1), + Y(Y0).reverse().slice(1)) + ] + }; + }; - transition.each(function() { - var schedule = set$3(this, id); - (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); - }); + graticule.extent = function(_) { + if (!arguments.length) return graticule.extentMinor(); + return graticule.extentMajor(_).extentMinor(_); + }; - return function(node) { - return get$1(node, id).value[name]; + graticule.extentMajor = 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); }; -} -var interpolate$1 = function(a, b) { - var c; - return (typeof b === "number" ? interpolateNumber - : b instanceof color ? interpolateRgb - : (c = color(b)) ? (b = c, interpolateRgb) - : interpolateString)(a, b); -}; + graticule.extentMinor = 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); + }; -function attrRemove$1(name) { - return function() { - this.removeAttribute(name); + graticule.step = function(_) { + if (!arguments.length) return graticule.stepMinor(); + return graticule.stepMajor(_).stepMinor(_); }; -} -function attrRemoveNS$1(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); + graticule.stepMajor = function(_) { + if (!arguments.length) return [DX, DY]; + DX = +_[0], DY = +_[1]; + return graticule; }; -} -function attrConstant$1(name, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = this.getAttribute(name); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); + graticule.stepMinor = function(_) { + if (!arguments.length) return [dx, dy]; + dx = +_[0], dy = +_[1]; + return graticule; }; -} -function attrConstantNS$1(fullname, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = this.getAttributeNS(fullname.space, fullname.local); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = graticuleX(y0, y1, 90); + y = graticuleY(x0, x1, precision); + X = graticuleX(Y0, Y1, 90); + Y = graticuleY(X0, X1, precision); + return graticule; }; + + return graticule + .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]]) + .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]); } -function attrFunction$1(name, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0, value1 = value(this); - if (value1 == null) return void this.removeAttribute(name); - value0 = this.getAttribute(name); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; +function graticule10() { + return graticule()(); } -function attrFunctionNS$1(fullname, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0, value1 = value(this); - if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); - value0 = this.getAttributeNS(fullname.space, fullname.local); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); +var interpolate$1 = function(a, b) { + var x0 = a[0] * radians, + y0 = a[1] * radians, + x1 = b[0] * radians, + y1 = b[1] * radians, + cy0 = cos$1(y0), + sy0 = sin$1(y0), + cy1 = cos$1(y1), + sy1 = sin$1(y1), + kx0 = cy0 * cos$1(x0), + ky0 = cy0 * sin$1(x0), + kx1 = cy1 * cos$1(x1), + ky1 = cy1 * sin$1(x1), + d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), + k = sin$1(d); + + var interpolate = d ? function(t) { + var B = sin$1(t *= d) / k, + A = sin$1(d - t) / k, + x = A * kx0 + B * kx1, + y = A * ky0 + B * ky1, + z = A * sy0 + B * sy1; + return [ + atan2(y, x) * degrees$1, + atan2(z, sqrt(x * x + y * y)) * degrees$1 + ]; + } : function() { + return [x0 * degrees$1, y0 * degrees$1]; }; -} -var transition_attr = function(name, value) { - var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$1; - return this.attrTween(name, typeof value === "function" - ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) - : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) - : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value)); + interpolate.distance = d; + + return interpolate; +}; + +var identity$4 = function(x) { + return x; }; -function attrTweenNS(fullname, value) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.setAttributeNS(fullname.space, fullname.local, i(t)); - }; - } - tween._value = value; - return tween; -} +var areaSum$1 = adder(); +var areaRingSum$1 = adder(); +var x00; +var y00; +var x0$1; +var y0$1; -function attrTween(name, value) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.setAttribute(name, i(t)); - }; +var areaStream$1 = { + point: noop$1, + lineStart: noop$1, + lineEnd: noop$1, + polygonStart: function() { + areaStream$1.lineStart = areaRingStart$1; + areaStream$1.lineEnd = areaRingEnd$1; + }, + polygonEnd: function() { + areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$1; + areaSum$1.add(abs(areaRingSum$1)); + areaRingSum$1.reset(); + }, + result: function() { + var area = areaSum$1 / 2; + areaSum$1.reset(); + return area; } - tween._value = value; - return tween; -} - -var transition_attrTween = function(name, value) { - var key = "attr." + name; - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - var fullname = namespace(name); - return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); }; -function delayFunction(id, value) { - return function() { - init(this, id).delay = +value.apply(this, arguments); - }; +function areaRingStart$1() { + areaStream$1.point = areaPointFirst$1; } -function delayConstant(id, value) { - return value = +value, function() { - init(this, id).delay = value; - }; +function areaPointFirst$1(x, y) { + areaStream$1.point = areaPoint$1; + x00 = x0$1 = x, y00 = y0$1 = y; } -var transition_delay = function(value) { - var id = this._id; - - return arguments.length - ? this.each((typeof value === "function" - ? delayFunction - : delayConstant)(id, value)) - : get$1(this.node(), id).delay; -}; - -function durationFunction(id, value) { - return function() { - set$3(this, id).duration = +value.apply(this, arguments); - }; +function areaPoint$1(x, y) { + areaRingSum$1.add(y0$1 * x - x0$1 * y); + x0$1 = x, y0$1 = y; } -function durationConstant(id, value) { - return value = +value, function() { - set$3(this, id).duration = value; - }; +function areaRingEnd$1() { + areaPoint$1(x00, y00); } -var transition_duration = function(value) { - var id = this._id; +var x0$2 = Infinity; +var y0$2 = x0$2; +var x1 = -x0$2; +var y1 = x1; - return arguments.length - ? this.each((typeof value === "function" - ? durationFunction - : durationConstant)(id, value)) - : get$1(this.node(), id).duration; +var boundsStream$1 = { + point: boundsPoint$1, + lineStart: noop$1, + lineEnd: noop$1, + polygonStart: noop$1, + polygonEnd: noop$1, + result: function() { + var bounds = [[x0$2, y0$2], [x1, y1]]; + x1 = y1 = -(y0$2 = x0$2 = Infinity); + return bounds; + } }; -function easeConstant(id, value) { - if (typeof value !== "function") throw new Error; - return function() { - set$3(this, id).ease = value; - }; +function boundsPoint$1(x, y) { + if (x < x0$2) x0$2 = x; + if (x > x1) x1 = x; + if (y < y0$2) y0$2 = y; + if (y > y1) y1 = y; } -var transition_ease = function(value) { - var id = this._id; +// TODO Enforce positive area for exterior, negative area for interior? - return arguments.length - ? this.each(easeConstant(id, value)) - : get$1(this.node(), id).ease; +var X0$1 = 0; +var Y0$1 = 0; +var Z0$1 = 0; +var X1$1 = 0; +var Y1$1 = 0; +var Z1$1 = 0; +var X2$1 = 0; +var Y2$1 = 0; +var Z2$1 = 0; +var x00$1; +var y00$1; +var x0$3; +var y0$3; + +var centroidStream$1 = { + point: centroidPoint$1, + lineStart: centroidLineStart$1, + lineEnd: centroidLineEnd$1, + polygonStart: function() { + centroidStream$1.lineStart = centroidRingStart$1; + centroidStream$1.lineEnd = centroidRingEnd$1; + }, + polygonEnd: function() { + centroidStream$1.point = centroidPoint$1; + centroidStream$1.lineStart = centroidLineStart$1; + centroidStream$1.lineEnd = centroidLineEnd$1; + }, + result: function() { + var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] + : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] + : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] + : [NaN, NaN]; + X0$1 = Y0$1 = Z0$1 = + X1$1 = Y1$1 = Z1$1 = + X2$1 = Y2$1 = Z2$1 = 0; + return centroid; + } }; -var transition_filter = function(match) { - if (typeof match !== "function") match = matcher$1(match); +function centroidPoint$1(x, y) { + X0$1 += x; + Y0$1 += y; + ++Z0$1; +} - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } +function centroidLineStart$1() { + centroidStream$1.point = centroidPointFirstLine; +} - return new Transition(subgroups, this._parents, this._name, this._id); -}; +function centroidPointFirstLine(x, y) { + centroidStream$1.point = centroidPointLine; + centroidPoint$1(x0$3 = x, y0$3 = y); +} -var transition_merge = function(transition) { - if (transition._id !== this._id) throw new Error; +function centroidPointLine(x, y) { + var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy); + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + centroidPoint$1(x0$3 = x, y0$3 = y); +} - for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } - } +function centroidLineEnd$1() { + centroidStream$1.point = centroidPoint$1; +} - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } +function centroidRingStart$1() { + centroidStream$1.point = centroidPointFirstRing; +} - return new Transition(merges, this._parents, this._name, this._id); -}; +function centroidRingEnd$1() { + centroidPointRing(x00$1, y00$1); +} -function start$1(name) { - return (name + "").trim().split(/^|\s+/).every(function(t) { - var i = t.indexOf("."); - if (i >= 0) t = t.slice(0, i); - return !t || t === "start"; - }); +function centroidPointFirstRing(x, y) { + centroidStream$1.point = centroidPointRing; + centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); } -function onFunction(id, name, listener) { - var on0, on1, sit = start$1(name) ? init : set$3; - return function() { - var schedule = sit(this, id), - on = schedule.on; +function centroidPointRing(x, y) { + var dx = x - x0$3, + dy = y - y0$3, + z = sqrt(dx * dx + dy * dy); - // If this node shared a dispatch with the previous node, - // just assign the updated shared dispatch and we’re done! - // Otherwise, copy-on-write. - if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; - schedule.on = on1; - }; + z = y0$3 * x - x0$3 * y; + X2$1 += z * (x0$3 + x); + Y2$1 += z * (y0$3 + y); + Z2$1 += z * 3; + centroidPoint$1(x0$3 = x, y0$3 = y); } -var transition_on = function(name, listener) { - var id = this._id; +function PathContext(context) { + this._context = context; +} - return arguments.length < 2 - ? get$1(this.node(), id).on.on(name) - : this.each(onFunction(id, name, listener)); +PathContext.prototype = { + _radius: 4.5, + pointRadius: function(_) { + return this._radius = _, this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._context.closePath(); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._context.moveTo(x, y); + this._point = 1; + break; + } + case 1: { + this._context.lineTo(x, y); + break; + } + default: { + this._context.moveTo(x + this._radius, y); + this._context.arc(x, y, this._radius, 0, tau$3); + break; + } + } + }, + result: noop$1 }; -function removeFunction(id) { - return function() { - var parent = this.parentNode; - for (var i in this.__transition) if (+i !== id) return; - if (parent) parent.removeChild(this); - }; +function PathString() { + this._string = []; } -var transition_remove = function() { - return this.on("end.remove", removeFunction(this._id)); -}; - -var transition_select = function(select$$1) { - var name = this._name, - id = this._id; - - if (typeof select$$1 !== "function") select$$1 = selector(select$$1); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; - schedule(subgroup[i], name, id, i, subgroup, get$1(node, id)); +PathString.prototype = { + _circle: circle$1(4.5), + pointRadius: function(_) { + return this._circle = circle$1(_), this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._string.push("Z"); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._string.push("M", x, ",", y); + this._point = 1; + break; + } + case 1: { + this._string.push("L", x, ",", y); + break; + } + default: { + this._string.push("M", x, ",", y, this._circle); + break; } } + }, + result: function() { + if (this._string.length) { + var result = this._string.join(""); + this._string = []; + return result; + } } - - return new Transition(subgroups, this._parents, name, id); }; -var transition_selectAll = function(select$$1) { - var name = this._name, - id = this._id; +function circle$1(radius) { + return "m0," + radius + + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + + "z"; +} - if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1); +var index$1 = function(projection, context) { + var pointRadius = 4.5, + projectionStream, + contextStream; - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - for (var children = select$$1.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) { - if (child = children[k]) { - schedule(child, name, id, k, children, inherit); - } - } - subgroups.push(children); - parents.push(node); - } + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + geoStream(object, projectionStream(contextStream)); } + return contextStream.result(); } - return new Transition(subgroups, parents, name, id); -}; - -var Selection$1 = selection.prototype.constructor; + path.area = function(object) { + geoStream(object, projectionStream(areaStream$1)); + return areaStream$1.result(); + }; -var transition_selection = function() { - return new Selection$1(this._groups, this._parents); -}; + path.bounds = function(object) { + geoStream(object, projectionStream(boundsStream$1)); + return boundsStream$1.result(); + }; -function styleRemove$1(name, interpolate$$1) { - var value00, - value10, - interpolate0; - return function() { - var style = window(this).getComputedStyle(this, null), - value0 = style.getPropertyValue(name), - value1 = (this.style.removeProperty(name), style.getPropertyValue(name)); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + path.centroid = function(object) { + geoStream(object, projectionStream(centroidStream$1)); + return centroidStream$1.result(); }; -} -function styleRemoveEnd(name) { - return function() { - this.style.removeProperty(name); + path.projection = function(_) { + return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection; }; -} -function styleConstant$1(name, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = window(this).getComputedStyle(this, null).getPropertyValue(name); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); + path.context = function(_) { + if (!arguments.length) return context; + contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return path; }; -} -function styleFunction$1(name, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var style = window(this).getComputedStyle(this, null), - value0 = style.getPropertyValue(name), - value1 = value(this); - if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name)); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; }; -} -var transition_style = function(name, value, priority) { - var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$1; - return value == null ? this - .styleTween(name, styleRemove$1(name, i)) - .on("end.style." + name, styleRemoveEnd(name)) - : this.styleTween(name, typeof value === "function" - ? styleFunction$1(name, i, tweenValue(this, "style." + name, value)) - : styleConstant$1(name, i, value), priority); + return path.projection(projection).context(context); }; -function styleTween(name, value, priority) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.style.setProperty(name, i(t), priority); - }; - } - tween._value = value; - return tween; -} +var sum$1 = adder(); -var transition_styleTween = function(name, value, priority) { - var key = "style." + (name += ""); - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); -}; +var polygonContains = function(polygon, point) { + var lambda = point[0], + phi = point[1], + normal = [sin$1(lambda), -cos$1(lambda), 0], + angle = 0, + winding = 0; -function textConstant$1(value) { - return function() { - this.textContent = value; - }; -} + sum$1.reset(); -function textFunction$1(value) { - return function() { - var value1 = value(this); - this.textContent = value1 == null ? "" : value1; - }; -} + for (var i = 0, n = polygon.length; i < n; ++i) { + if (!(m = (ring = polygon[i]).length)) continue; + var ring, + m, + point0 = ring[m - 1], + lambda0 = point0[0], + phi0 = point0[1] / 2 + quarterPi, + sinPhi0 = sin$1(phi0), + cosPhi0 = cos$1(phi0); -var transition_text = function(value) { - return this.tween("text", typeof value === "function" - ? textFunction$1(tweenValue(this, "text", value)) - : textConstant$1(value == null ? "" : value + "")); -}; + for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { + var point1 = ring[j], + lambda1 = point1[0], + phi1 = point1[1] / 2 + quarterPi, + sinPhi1 = sin$1(phi1), + cosPhi1 = cos$1(phi1), + delta = lambda1 - lambda0, + sign$$1 = delta >= 0 ? 1 : -1, + absDelta = sign$$1 * delta, + antimeridian = absDelta > pi$3, + k = sinPhi0 * sinPhi1; -var transition_transition = function() { - var name = this._name, - id0 = this._id, - id1 = newId(); + sum$1.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta))); + angle += antimeridian ? delta + sign$$1 * tau$3 : delta; - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - var inherit = get$1(node, id0); - schedule(node, name, id1, i, group, { - time: inherit.time + inherit.delay + inherit.duration, - delay: 0, - duration: inherit.duration, - ease: inherit.ease - }); + // Are the longitudes either side of the point’s meridian (lambda), + // and are the latitudes smaller than the parallel (phi)? + if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { + var arc = cartesianCross(cartesian(point0), cartesian(point1)); + cartesianNormalizeInPlace(arc); + var intersection = cartesianCross(normal, arc); + cartesianNormalizeInPlace(intersection); + var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]); + if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { + winding += antimeridian ^ delta >= 0 ? 1 : -1; + } } } } - return new Transition(groups, this._parents, name, id1); -}; - -var id = 0; - -function Transition(groups, parents, name, id) { - this._groups = groups; - this._parents = parents; - this._name = name; - this._id = id; -} + // First, determine whether the South pole is inside or outside: + // + // It is inside if: + // * the polygon winds around it in a clockwise direction. + // * the polygon does not (cumulatively) wind around it, but has a negative + // (counter-clockwise) area. + // + // Second, count the (signed) number of times a segment crosses a lambda + // from the point to the South pole. If it is zero, then the point is the + // same side as the South pole. -function transition(name) { - return selection().transition(name); -} + return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1); +}; -function newId() { - return ++id; -} +var clip = function(pointVisible, clipLine, interpolate, start) { + return function(rotate, sink) { + var line = clipLine(sink), + rotatedStart = rotate.invert(start[0], start[1]), + ringBuffer = clipBuffer(), + ringSink = clipLine(ringBuffer), + polygonStarted = false, + polygon, + segments, + ring; -var selection_prototype = selection.prototype; + 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 = merge(segments); + var startInside = polygonContains(polygon, rotatedStart); + if (segments.length) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + clipPolygon(segments, compareIntersection, startInside, interpolate, sink); + } else if (startInside) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + } + if (polygonStarted) sink.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + sink.polygonStart(); + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + sink.polygonEnd(); + } + }; -Transition.prototype = transition.prototype = { - constructor: Transition, - select: transition_select, - selectAll: transition_selectAll, - filter: transition_filter, - merge: transition_merge, - selection: transition_selection, - transition: transition_transition, - call: selection_prototype.call, - nodes: selection_prototype.nodes, - node: selection_prototype.node, - size: selection_prototype.size, - empty: selection_prototype.empty, - each: selection_prototype.each, - on: transition_on, - attr: transition_attr, - attrTween: transition_attrTween, - style: transition_style, - styleTween: transition_styleTween, - text: transition_text, - remove: transition_remove, - tween: transition_tween, - delay: transition_delay, - duration: transition_duration, - ease: transition_ease -}; + function point(lambda, phi) { + var point = rotate(lambda, phi); + if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi); + } -var defaultTiming = { - time: null, // Set on use. - delay: 0, - duration: 250, - ease: cubicInOut -}; + function pointLine(lambda, phi) { + var point = rotate(lambda, phi); + line.point(point[0], point[1]); + } -function inherit(node, id) { - var timing; - while (!(timing = node.__transition) || !(timing = timing[id])) { - if (!(node = node.parentNode)) { - return defaultTiming.time = now(), defaultTiming; + function lineStart() { + clip.point = pointLine; + line.lineStart(); } - } - return timing; -} -var selection_transition = function(name) { - var id, - timing; + function lineEnd() { + clip.point = point; + line.lineEnd(); + } - if (name instanceof Transition) { - id = name._id, name = name._name; - } else { - id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; - } + function pointRing(lambda, phi) { + ring.push([lambda, phi]); + var point = rotate(lambda, phi); + ringSink.point(point[0], point[1]); + } - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - schedule(node, name, id, i, group, timing || inherit(node, id)); - } + function ringStart() { + ringSink.lineStart(); + ring = []; } - } - return new Transition(groups, this._parents, name, id); -}; + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringSink.lineEnd(); -selection.prototype.interrupt = selection_interrupt; -selection.prototype.transition = selection_transition; + var clean = ringSink.clean(), + ringSegments = ringBuffer.result(), + i, n = ringSegments.length, m, + segment, + point; -var root$1 = [null]; + ring.pop(); + polygon.push(ring); + ring = null; -var active = function(node, name) { - var schedules = node.__transition, - schedule, - i; + if (!n) return; - if (schedules) { - name = name == null ? null : name + ""; - for (i in schedules) { - if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { - return new Transition([[node]], root$1, name, +i); + // No intersections. + if (clean & 1) { + segment = ringSegments[0]; + if ((m = segment.length - 1) > 0) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); + sink.lineEnd(); + } + return; } + + // Rejoin connected segments. + // TODO reuse ringBuffer.rejoin()? + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + + segments.push(ringSegments.filter(validSegment)); } - } - return null; + return clip; + }; }; -var slice$4 = Array.prototype.slice; +function validSegment(segment) { + return segment.length > 1; +} -var identity$5 = function(x) { - return x; -}; +// Intersections are sorted along the clip edge. For both antimeridian cutting +// and circle clipping, the same comparison is used. +function compareIntersection(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1]) + - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]); +} -var top = 1; -var right = 2; -var bottom = 3; -var left = 4; -var epsilon$2 = 1e-6; +var clipAntimeridian = clip( + function() { return true; }, + clipAntimeridianLine, + clipAntimeridianInterpolate, + [-pi$3, -halfPi$2] +); -function translateX(scale0, scale1, d) { - var x = scale0(d); - return "translate(" + (isFinite(x) ? x : scale1(d)) + ",0)"; +// Takes a line and cuts into visible segments. Return values: 0 - there were +// intersections or the line was empty; 1 - no intersections; 2 - there were +// intersections, and the first and last segments should be rejoined. +function clipAntimeridianLine(stream) { + var lambda0 = NaN, + phi0 = NaN, + sign0 = NaN, + clean; // no intersections + + return { + lineStart: function() { + stream.lineStart(); + clean = 1; + }, + point: function(lambda1, phi1) { + var sign1 = lambda1 > 0 ? pi$3 : -pi$3, + delta = abs(lambda1 - lambda0); + if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole + stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + stream.point(lambda1, phi0); + clean = 0; + } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian + if (abs(lambda0 - sign0) < epsilon$2) lambda0 -= sign0 * epsilon$2; // handle degeneracies + if (abs(lambda1 - sign1) < epsilon$2) lambda1 -= sign1 * epsilon$2; + phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + clean = 0; + } + stream.point(lambda0 = lambda1, phi0 = phi1); + sign0 = sign1; + }, + lineEnd: function() { + stream.lineEnd(); + lambda0 = phi0 = NaN; + }, + clean: function() { + return 2 - clean; // if intersections, rejoin first and last segments + } + }; } -function translateY(scale0, scale1, d) { - var y = scale0(d); - return "translate(0," + (isFinite(y) ? y : scale1(d)) + ")"; +function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { + var cosPhi0, + cosPhi1, + sinLambda0Lambda1 = sin$1(lambda0 - lambda1); + return abs(sinLambda0Lambda1) > epsilon$2 + ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1) + - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0)) + / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) + : (phi0 + phi1) / 2; } -function center(scale) { - var offset = scale.bandwidth() / 2; - if (scale.round()) offset = Math.round(offset); - return function(d) { - return scale(d) + offset; - }; +function clipAntimeridianInterpolate(from, to, direction, stream) { + var phi; + if (from == null) { + phi = direction * halfPi$2; + stream.point(-pi$3, phi); + stream.point(0, phi); + stream.point(pi$3, phi); + stream.point(pi$3, 0); + stream.point(pi$3, -phi); + stream.point(0, -phi); + stream.point(-pi$3, -phi); + stream.point(-pi$3, 0); + stream.point(-pi$3, phi); + } else if (abs(from[0] - to[0]) > epsilon$2) { + var lambda = from[0] < to[0] ? pi$3 : -pi$3; + phi = direction * lambda / 2; + stream.point(-lambda, phi); + stream.point(0, phi); + stream.point(lambda, phi); + } else { + stream.point(to[0], to[1]); + } } -function entering() { - return !this.__axis; -} +var clipCircle = function(radius, delta) { + var cr = cos$1(radius), + smallRadius = cr > 0, + notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case -function axis(orient, scale) { - var tickArguments = [], - tickValues = null, - tickFormat = null, - tickSizeInner = 6, - tickSizeOuter = 6, - tickPadding = 3; + function interpolate(from, to, direction, stream) { + circleStream(stream, radius, delta, direction, from, to); + } - function axis(context) { - var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, - format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$5) : tickFormat, - spacing = Math.max(tickSizeInner, 0) + tickPadding, - transform = orient === top || orient === bottom ? translateX : translateY, - range = scale.range(), - range0 = range[0] + 0.5, - range1 = range[range.length - 1] + 0.5, - position = (scale.bandwidth ? center : identity$5)(scale.copy()), - selection = context.selection ? context.selection() : context, - path = selection.selectAll(".domain").data([null]), - tick = selection.selectAll(".tick").data(values, scale).order(), - tickExit = tick.exit(), - tickEnter = tick.enter().append("g").attr("class", "tick"), - line = tick.select("line"), - text = tick.select("text"), - k = orient === top || orient === left ? -1 : 1, - x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x"); + function visible(lambda, phi) { + return cos$1(lambda) * cos$1(phi) > cr; + } - path = path.merge(path.enter().insert("path", ".tick") - .attr("class", "domain") - .attr("stroke", "#000")); + // Takes a line and cuts into visible segments. Return values used for polygon + // clipping: 0 - there were intersections or the line was empty; 1 - no + // intersections 2 - there were intersections, and the first and last segments + // should be rejoined. + function clipLine(stream) { + var point0, // previous point + c0, // code for previous point + v0, // visibility of previous point + v00, // visibility of first point + clean; // no intersections + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(lambda, phi) { + var point1 = [lambda, phi], + point2, + v = visible(lambda, phi), + c = smallRadius + ? v ? 0 : code(lambda, phi) + : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0; + if (!point0 && (v00 = v0 = v)) stream.lineStart(); + // Handle degeneracies. + // TODO ignore if not clipping polygons. + if (v !== v0) { + point2 = intersect(point0, point1); + if (pointEqual(point0, point2) || pointEqual(point1, point2)) { + point1[0] += epsilon$2; + point1[1] += epsilon$2; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + // outside going in + stream.lineStart(); + point2 = intersect(point1, point0); + stream.point(point2[0], point2[1]); + } else { + // inside going out + point2 = intersect(point0, point1); + stream.point(point2[0], point2[1]); + stream.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + // If the codes for two points are different, or are both zero, + // and there this segment intersects with the small circle. + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + } else { + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !pointEqual(point0, point1))) { + stream.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) stream.lineEnd(); + point0 = null; + }, + // Rejoin first and last segments if there were intersections and the first + // and last points were visible. + clean: function() { + return clean | ((v00 && v0) << 1); + } + }; + } - tick = tick.merge(tickEnter); + // Intersects the great circle between a and b with the clip circle. + function intersect(a, b, two) { + var pa = cartesian(a), + pb = cartesian(b); - line = line.merge(tickEnter.append("line") - .attr("stroke", "#000") - .attr(x + "2", k * tickSizeInner) - .attr(y + "1", 0.5) - .attr(y + "2", 0.5)); + // We have two planes, n1.p = d1 and n2.p = d2. + // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). + var n1 = [1, 0, 0], // normal + n2 = cartesianCross(pa, pb), + n2n2 = cartesianDot(n2, n2), + n1n2 = n2[0], // cartesianDot(n1, n2), + determinant = n2n2 - n1n2 * n1n2; - text = text.merge(tickEnter.append("text") - .attr("fill", "#000") - .attr(x, k * spacing) - .attr(y, 0.5) - .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); + // Two polar points. + if (!determinant) return !two && a; - if (context !== selection) { - path = path.transition(context); - tick = tick.transition(context); - line = line.transition(context); - text = text.transition(context); + var c1 = cr * n2n2 / determinant, + c2 = -cr * n1n2 / determinant, + n1xn2 = cartesianCross(n1, n2), + A = cartesianScale(n1, c1), + B = cartesianScale(n2, c2); + cartesianAddInPlace(A, B); - tickExit = tickExit.transition(context) - .attr("opacity", epsilon$2) - .attr("transform", function(d) { return transform(position, this.parentNode.__axis || position, d); }); + // Solve |p(t)|^2 = 1. + var u = n1xn2, + w = cartesianDot(A, u), + uu = cartesianDot(u, u), + t2 = w * w - uu * (cartesianDot(A, A) - 1); - tickEnter - .attr("opacity", epsilon$2) - .attr("transform", function(d) { return transform(this.parentNode.__axis || position, position, d); }); - } + if (t2 < 0) return; - tickExit.remove(); + var t = sqrt(t2), + q = cartesianScale(u, (-w - t) / uu); + cartesianAddInPlace(q, A); + q = spherical(q); - path - .attr("d", orient === left || orient == right - ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter - : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter); + if (!two) return q; - tick - .attr("opacity", 1) - .attr("transform", function(d) { return transform(position, position, d); }); + // Two intersection points. + var lambda0 = a[0], + lambda1 = b[0], + phi0 = a[1], + phi1 = b[1], + z; - line - .attr(x + "2", k * tickSizeInner); + if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; - text - .attr(x, k * spacing) - .text(format); + var delta = lambda1 - lambda0, + polar = abs(delta - pi$3) < epsilon$2, + meridian = polar || delta < epsilon$2; - selection.filter(entering) - .attr("fill", "none") - .attr("font-size", 10) - .attr("font-family", "sans-serif") - .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); + if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; - selection - .each(function() { this.__axis = position; }); + // Check that the first point is between a and b. + if (meridian + ? polar + ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1) + : phi0 <= q[1] && q[1] <= phi1 + : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) { + var q1 = cartesianScale(u, (-w + t) / uu); + cartesianAddInPlace(q1, A); + return [q, spherical(q1)]; + } } - axis.scale = function(_) { - return arguments.length ? (scale = _, axis) : scale; - }; - - axis.ticks = function() { - return tickArguments = slice$4.call(arguments), axis; - }; + // Generates a 4-bit vector representing the location of a point relative to + // the small circle's bounding box. + function code(lambda, phi) { + var r = smallRadius ? radius : pi$3 - radius, + code = 0; + if (lambda < -r) code |= 1; // left + else if (lambda > r) code |= 2; // right + if (phi < -r) code |= 4; // below + else if (phi > r) code |= 8; // above + return code; + } - axis.tickArguments = function(_) { - return arguments.length ? (tickArguments = _ == null ? [] : slice$4.call(_), axis) : tickArguments.slice(); - }; + return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]); +}; - axis.tickValues = function(_) { - return arguments.length ? (tickValues = _ == null ? null : slice$4.call(_), axis) : tickValues && tickValues.slice(); +var transform = function(methods) { + return { + stream: transformer(methods) }; +}; - axis.tickFormat = function(_) { - return arguments.length ? (tickFormat = _, axis) : tickFormat; +function transformer(methods) { + return function(stream) { + var s = new TransformStream; + for (var key in methods) s[key] = methods[key]; + s.stream = stream; + return s; }; +} - axis.tickSize = function(_) { - return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; - }; +function TransformStream() {} - axis.tickSizeInner = function(_) { - return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; - }; +TransformStream.prototype = { + constructor: TransformStream, + 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(); } +}; - axis.tickSizeOuter = function(_) { - return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; - }; +function fitExtent(projection, extent, object) { + var w = extent[1][0] - extent[0][0], + h = extent[1][1] - extent[0][1], + clip = projection.clipExtent && projection.clipExtent(); - axis.tickPadding = function(_) { - return arguments.length ? (tickPadding = +_, axis) : tickPadding; - }; + projection + .scale(150) + .translate([0, 0]); - return axis; -} + if (clip != null) projection.clipExtent(null); -function axisTop(scale) { - return axis(top, scale); -} + geoStream(object, projection.stream(boundsStream$1)); -function axisRight(scale) { - return axis(right, scale); -} + var b = boundsStream$1.result(), + k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), + x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, + y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; -function axisBottom(scale) { - return axis(bottom, scale); -} + if (clip != null) projection.clipExtent(clip); -function axisLeft(scale) { - return axis(left, scale); + return projection + .scale(k * 150) + .translate([x, y]); } -function defaultSeparation(a, b) { - return a.parent === b.parent ? 1 : 2; +function fitSize(projection, size, object) { + return fitExtent(projection, [[0, 0], size], object); } -function meanX(children) { - return children.reduce(meanXReduce, 0) / children.length; -} +var maxDepth = 16; +var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance) -function meanXReduce(x, c) { - return x + c.x; -} +var resample = function(project, delta2) { + return +delta2 ? resample$1(project, delta2) : resampleNone(project); +}; -function maxY(children) { - return 1 + children.reduce(maxYReduce, 0); +function resampleNone(project) { + return transformer({ + point: function(x, y) { + x = project(x, y); + this.stream.point(x[0], x[1]); + } + }); } -function maxYReduce(y, c) { - return Math.max(y, c.y); -} +function resample$1(project, delta2) { -function leafLeft(node) { - var children; - while (children = node.children) node = children[0]; - return node; -} + function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, + dy = y1 - y0, + d2 = dx * dx + dy * dy; + if (d2 > 4 * delta2 && depth--) { + var a = a0 + a1, + b = b0 + b1, + c = c0 + c1, + m = sqrt(a * a + b * b + c * c), + phi2 = asin(c /= m), + lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a), + p = project(lambda2, phi2), + x2 = p[0], + y2 = p[1], + dx2 = x2 - x0, + dy2 = y2 - y0, + dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > delta2 // perpendicular projected distance + || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end + || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); + } + } + } + return function(stream) { + var lambda00, x00, y00, a00, b00, c00, // first point + lambda0, x0, y0, a0, b0, c0; // previous point -function leafRight(node) { - var children; - while (children = node.children) node = children[children.length - 1]; - return node; -} + var resampleStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; }, + polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; } + }; -var cluster = function() { - var separation = defaultSeparation, - dx = 1, - dy = 1, - nodeSize = false; + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } - function cluster(root) { - var previousNode, - x = 0; + function lineStart() { + x0 = NaN; + resampleStream.point = linePoint; + stream.lineStart(); + } - // First walk, computing the initial x & y values. - root.eachAfter(function(node) { - var children = node.children; - if (children) { - node.x = meanX(children); - node.y = maxY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); + function linePoint(lambda, phi) { + var c = cartesian([lambda, phi]), p = project(lambda, phi); + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } - var left = leafLeft(root), - right = leafRight(root), - x0 = left.x - separation(left, right) / 2, - x1 = right.x + separation(right, left) / 2; + function lineEnd() { + resampleStream.point = point; + stream.lineEnd(); + } - // Second walk, normalizing x & y to the desired size. - return root.eachAfter(nodeSize ? function(node) { - node.x = (node.x - root.x) * dx; - node.y = (root.y - node.y) * dy; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * dx; - node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; - }); - } + function ringStart() { + lineStart(); + resampleStream.point = ringPoint; + resampleStream.lineEnd = ringEnd; + } - cluster.separation = function(x) { - return arguments.length ? (separation = x, cluster) : separation; - }; + function ringPoint(lambda, phi) { + linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resampleStream.point = linePoint; + } - cluster.size = function(x) { - return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); - }; + function ringEnd() { + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); + resampleStream.lineEnd = lineEnd; + lineEnd(); + } - cluster.nodeSize = function(x) { - return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); + return resampleStream; }; +} - return cluster; -}; +var transformRadians = transformer({ + point: function(x, y) { + this.stream.point(x * radians, y * radians); + } +}); -var node_each = function(callback) { - var node = this, current, next = [node], children, i, n; - do { - current = next.reverse(), next = []; - while (node = current.pop()) { - callback(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - next.push(children[i]); - } - } - } while (next.length); - return this; -}; +function projection(project) { + return projectionMutator(function() { return project; })(); +} -var node_eachBefore = function(callback) { - var node = this, nodes = [node], children, i; - while (node = nodes.pop()) { - callback(node), children = node.children; - if (children) for (i = children.length - 1; i >= 0; --i) { - nodes.push(children[i]); - } +function projectionMutator(projectAt) { + var project, + k = 150, // scale + x = 480, y = 250, // translate + dx, dy, lambda = 0, phi = 0, // center + deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate + theta = null, preclip = clipAntimeridian, // clip angle + x0 = null, y0, x1, y1, postclip = identity$4, // clip extent + delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision + cache, + cacheStream; + + function projection(point) { + point = projectRotate(point[0] * radians, point[1] * radians); + return [point[0] * k + dx, dy - point[1] * k]; } - return this; -}; -var node_eachAfter = function(callback) { - var node = this, nodes = [node], next = [], children, i, n; - while (node = nodes.pop()) { - next.push(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - nodes.push(children[i]); - } + function invert(point) { + point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); + return point && [point[0] * degrees$1, point[1] * degrees$1]; } - while (node = next.pop()) { - callback(node); + + function projectTransform(x, y) { + return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; } - return this; -}; -var node_sum = function(value) { - return this.eachAfter(function(node) { - var sum = +value(node.data) || 0, - children = node.children, - i = children && children.length; - while (--i >= 0) sum += children[i].value; - node.value = sum; - }); -}; + projection.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream)))); + }; -var node_sort = function(compare) { - return this.eachBefore(function(node) { - if (node.children) { - node.children.sort(compare); - } - }); -}; + projection.clipAngle = function(_) { + return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1; + }; -var node_path = function(end) { - var start = this, - ancestor = leastCommonAncestor(start, end), - nodes = [start]; - while (start !== ancestor) { - start = start.parent; - nodes.push(start); - } - var k = nodes.length; - while (end !== ancestor) { - nodes.splice(k, 0, end); - end = end.parent; - } - return nodes; -}; + projection.clipExtent = function(_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; -function leastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = a.ancestors(), - bNodes = b.ancestors(), - c = null; - a = aNodes.pop(); - b = bNodes.pop(); - while (a === b) { - c = a; - a = aNodes.pop(); - b = bNodes.pop(); - } - return c; -} + projection.scale = function(_) { + return arguments.length ? (k = +_, recenter()) : k; + }; -var node_ancestors = function() { - var node = this, nodes = [node]; - while (node = node.parent) { - nodes.push(node); - } - return nodes; -}; + projection.translate = function(_) { + return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; + }; -var node_descendants = function() { - var nodes = []; - this.each(function(node) { - nodes.push(node); - }); - return nodes; -}; + projection.center = function(_) { + return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1]; + }; -var node_leaves = function() { - var leaves = []; - this.eachBefore(function(node) { - if (!node.children) { - leaves.push(node); - } - }); - return leaves; -}; + projection.rotate = function(_) { + return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1]; + }; -var node_links = function() { - var root = this, links = []; - root.each(function(node) { - if (node !== root) { // Don’t include the root’s parent, if any. - links.push({source: node.parent, target: node}); - } - }); - return links; -}; + projection.precision = function(_) { + return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); + }; -function hierarchy(data, children) { - var root = new Node(data), - valued = +data.value && (root.value = data.value), - node, - nodes = [root], - child, - childs, - i, - n; + projection.fitExtent = function(extent, object) { + return fitExtent(projection, extent, object); + }; - if (children == null) children = defaultChildren; + projection.fitSize = function(size, object) { + return fitSize(projection, size, object); + }; - while (node = nodes.pop()) { - if (valued) node.value = +node.data.value; - if ((childs = children(node.data)) && (n = childs.length)) { - node.children = new Array(n); - for (i = n - 1; i >= 0; --i) { - nodes.push(child = node.children[i] = new Node(childs[i])); - child.parent = node; - child.depth = node.depth + 1; - } - } + function recenter() { + projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project); + var center = project(lambda, phi); + dx = x - center[0] * k; + dy = y + center[1] * k; + return reset(); } - return root.eachBefore(computeHeight); -} + function reset() { + cache = cacheStream = null; + return projection; + } -function node_copy() { - return hierarchy(this).eachBefore(copyData); + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return recenter(); + }; } -function defaultChildren(d) { - return d.children; -} +function conicProjection(projectAt) { + var phi0 = 0, + phi1 = pi$3 / 3, + m = projectionMutator(projectAt), + p = m(phi0, phi1); -function copyData(node) { - node.data = node.data.data; -} + p.parallels = function(_) { + return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1]; + }; -function computeHeight(node) { - var height = 0; - do node.height = height; - while ((node = node.parent) && (node.height < ++height)); + return p; } -function Node(data) { - this.data = data; - this.depth = - this.height = 0; - this.parent = null; -} +function cylindricalEqualAreaRaw(phi0) { + var cosPhi0 = cos$1(phi0); -Node.prototype = hierarchy.prototype = { - constructor: Node, - each: node_each, - eachAfter: node_eachAfter, - eachBefore: node_eachBefore, - sum: node_sum, - sort: node_sort, - path: node_path, - ancestors: node_ancestors, - descendants: node_descendants, - leaves: node_leaves, - links: node_links, - copy: node_copy -}; + function forward(lambda, phi) { + return [lambda * cosPhi0, sin$1(phi) / cosPhi0]; + } -function Node$2(value) { - this._ = value; - this.next = null; + forward.invert = function(x, y) { + return [x / cosPhi0, asin(y * cosPhi0)]; + }; + + return forward; } -var shuffle$1 = function(array) { - var i, - n = (array = array.slice()).length, - head = null, - node = head; +function conicEqualAreaRaw(y0, y1) { + var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2; - while (n) { - var next = new Node$2(array[n - 1]); - if (node) node = node.next = next; - else node = head = next; - array[i] = array[--n]; + // Are the parallels symmetrical around the Equator? + if (abs(n) < epsilon$2) return cylindricalEqualAreaRaw(y0); + + var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; + + function project(x, y) { + var r = sqrt(c - 2 * n * sin$1(y)) / n; + return [r * sin$1(x *= n), r0 - r * cos$1(x)]; } - return { - head: head, - tail: node + project.invert = function(x, y) { + var r0y = r0 - y; + return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; }; + + return project; +} + +var conicEqualArea = function() { + return conicProjection(conicEqualAreaRaw) + .scale(155.424) + .center([0, 33.6442]); }; -var enclose = function(circles) { - return encloseN(shuffle$1(circles), []); +var albers = function() { + return conicEqualArea() + .parallels([29.5, 45.5]) + .scale(1070) + .translate([480, 250]) + .rotate([96, 0]) + .center([-0.6, 38.7]); }; -function encloses(a, b) { - var dx = b.x - a.x, - dy = b.y - a.y, - dr = a.r - b.r; - return dr * dr + 1e-6 > dx * dx + dy * dy; +// The projections must have mutually exclusive clip regions on the sphere, +// as this will avoid emitting interleaving lines and polygons. +function multiplex(streams) { + var n = streams.length; + return { + point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); }, + sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); }, + lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); }, + lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); }, + polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); }, + polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); } + }; } -// Returns the smallest circle that contains circles L and intersects circles B. -function encloseN(L, B) { - var circle, - l0 = null, - l1 = L.head, - l2, - p1; +// A composite projection for the United States, configured by default for +// 960×500. The projection also works quite well at 960×600 if you change the +// scale to 1285 and adjust the translate accordingly. The set of standard +// parallels for each region comes from USGS, which is published here: +// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers +var albersUsa = function() { + var cache, + cacheStream, + lower48 = albers(), lower48Point, + alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 + hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 + point, pointStream = {point: function(x, y) { point = [x, y]; }}; - switch (B.length) { - case 1: circle = enclose1(B[0]); break; - case 2: circle = enclose2(B[0], B[1]); break; - case 3: circle = enclose3(B[0], B[1], B[2]); break; + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + return point = null, + (lower48Point.point(x, y), point) + || (alaskaPoint.point(x, y), point) + || (hawaiiPoint.point(x, y), point); } - while (l1) { - p1 = l1._, l2 = l1.next; - if (!circle || !encloses(circle, p1)) { + 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 >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska + : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii + : lower48).invert(coordinates); + }; - // Temporarily truncate L before l1. - if (l0) L.tail = l0, l0.next = null; - else L.head = L.tail = null; + albersUsa.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); + }; - B.push(p1); - circle = encloseN(L, B); // Note: reorders L! - B.pop(); + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_), alaska.precision(_), hawaii.precision(_); + return reset(); + }; - // Move l1 to the front of L and reconnect the truncated list L. - if (L.head) l1.next = L.head, L.head = l1; - else l1.next = null, L.head = L.tail = l1; - l0 = L.tail, l0.next = l2; + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; - } else { - l0 = l1; - } - l1 = l2; - } + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; - L.tail = l0; - return circle; -} + lower48Point = lower48 + .translate(_) + .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) + .stream(pointStream); -function enclose1(a) { - return { - x: a.x, - y: a.y, - r: a.r + alaskaPoint = alaska + .translate([x - 0.307 * k, y + 0.201 * k]) + .clipExtent([[x - 0.425 * k + epsilon$2, y + 0.120 * k + epsilon$2], [x - 0.214 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) + .stream(pointStream); + + hawaiiPoint = hawaii + .translate([x - 0.205 * k, y + 0.212 * k]) + .clipExtent([[x - 0.214 * k + epsilon$2, y + 0.166 * k + epsilon$2], [x - 0.115 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) + .stream(pointStream); + + return reset(); }; -} -function enclose2(a, b) { - var x1 = a.x, y1 = a.y, r1 = a.r, - x2 = b.x, y2 = b.y, r2 = b.r, - x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, - l = Math.sqrt(x21 * x21 + y21 * y21); - return { - x: (x1 + x2 + x21 / l * r21) / 2, - y: (y1 + y2 + y21 / l * r21) / 2, - r: (l + r1 + r2) / 2 + albersUsa.fitExtent = function(extent, object) { + return fitExtent(albersUsa, extent, object); }; -} -function enclose3(a, b, c) { - var x1 = a.x, y1 = a.y, r1 = a.r, - x2 = b.x, y2 = b.y, r2 = b.r, - x3 = c.x, y3 = c.y, r3 = c.r, - a2 = 2 * (x1 - x2), - b2 = 2 * (y1 - y2), - c2 = 2 * (r2 - r1), - d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2, - a3 = 2 * (x1 - x3), - b3 = 2 * (y1 - y3), - c3 = 2 * (r3 - r1), - d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3, - ab = a3 * b2 - a2 * b3, - xa = (b2 * d3 - b3 * d2) / ab - x1, - xb = (b3 * c2 - b2 * c3) / ab, - ya = (a3 * d2 - a2 * d3) / ab - y1, - yb = (a2 * c3 - a3 * c2) / ab, - A = xb * xb + yb * yb - 1, - B = 2 * (xa * xb + ya * yb + r1), - C = xa * xa + ya * ya - r1 * r1, - r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A); - return { - x: xa + xb * r + x1, - y: ya + yb * r + y1, - r: r + albersUsa.fitSize = function(size, object) { + return fitSize(albersUsa, size, object); }; -} -function place(a, b, c) { - var ax = a.x, - ay = a.y, - da = b.r + c.r, - db = a.r + c.r, - dx = b.x - ax, - dy = b.y - ay, - dc = dx * dx + dy * dy; - if (dc) { - var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), - y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = ax + x * dx + y * dy; - c.y = ay + x * dy - y * dx; - } else { - c.x = ax + db; - c.y = ay; + function reset() { + cache = cacheStream = null; + return albersUsa; } -} -function intersects(a, b) { - var dx = b.x - a.x, - dy = b.y - a.y, - dr = a.r + b.r; - return dr * dr > dx * dx + dy * dy; -} + return albersUsa.scale(1070); +}; -function distance2(circle, x, y) { - var dx = circle.x - x, - dy = circle.y - y; - return dx * dx + dy * dy; +function azimuthalRaw(scale) { + return function(x, y) { + var cx = cos$1(x), + cy = cos$1(y), + k = scale(cx * cy); + return [ + k * cy * sin$1(x), + k * sin$1(y) + ]; + } } -function Node$1(circle) { - this._ = circle; - this.next = null; - this.previous = null; +function azimuthalInvert(angle) { + return function(x, y) { + var z = sqrt(x * x + y * y), + c = angle(z), + sc = sin$1(c), + cc = cos$1(c); + return [ + atan2(x * sc, z * cc), + asin(z && y * sc / z) + ]; + } } -function packEnclose(circles) { - if (!(n = circles.length)) return 0; +var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { + return sqrt(2 / (1 + cxcy)); +}); - var a, b, c, n; +azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { + return 2 * asin(z / 2); +}); - // Place the first circle. - a = circles[0], a.x = 0, a.y = 0; - if (!(n > 1)) return a.r; +var azimuthalEqualArea = function() { + return projection(azimuthalEqualAreaRaw) + .scale(124.75) + .clipAngle(180 - 1e-3); +}; - // Place the second circle. - b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; - if (!(n > 2)) return a.r + b.r; +var azimuthalEquidistantRaw = azimuthalRaw(function(c) { + return (c = acos(c)) && c / sin$1(c); +}); - // Place the third circle. - place(b, a, c = circles[2]); +azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { + return z; +}); - // Initialize the weighted centroid. - var aa = a.r * a.r, - ba = b.r * b.r, - ca = c.r * c.r, - oa = aa + ba + ca, - ox = aa * a.x + ba * b.x + ca * c.x, - oy = aa * a.y + ba * b.y + ca * c.y, - cx, cy, i, j, k, sj, sk; +var azimuthalEquidistant = function() { + return projection(azimuthalEquidistantRaw) + .scale(79.4188) + .clipAngle(180 - 1e-3); +}; + +function mercatorRaw(lambda, phi) { + return [lambda, log(tan((halfPi$2 + phi) / 2))]; +} + +mercatorRaw.invert = function(x, y) { + return [x, 2 * atan(exp(y)) - halfPi$2]; +}; + +var mercator = function() { + return mercatorProjection(mercatorRaw) + .scale(961 / tau$3); +}; - // Initialize the front-chain using the first three circles a, b and c. - a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); - a.next = c.previous = b; - b.next = a.previous = c; - c.next = b.previous = a; +function mercatorProjection(project) { + var m = projection(project), + scale = m.scale, + translate = m.translate, + clipExtent = m.clipExtent, + clipAuto; - // Attempt to place each remaining circle… - pack: for (i = 3; i < n; ++i) { - place(a._, b._, c = circles[i]), c = new Node$1(c); + m.scale = function(_) { + return arguments.length ? (scale(_), clipAuto && m.clipExtent(null), m) : scale(); + }; - // If there are only three elements in the front-chain… - if ((k = a.previous) === (j = b.next)) { - // If the new circle intersects the third circle, - // rotate the front chain to try the next position. - if (intersects(j._, c._)) { - a = b, b = j, --i; - continue pack; - } - } + m.translate = function(_) { + return arguments.length ? (translate(_), clipAuto && m.clipExtent(null), m) : translate(); + }; - // Find the closest intersecting circle on the front-chain, if any. - else { - sj = j._.r, sk = k._.r; - do { - if (sj <= sk) { - if (intersects(j._, c._)) { - b = j, a.next = b, b.previous = a, --i; - continue pack; - } - j = j.next, sj += j._.r; - } else { - if (intersects(k._, c._)) { - a = k, a.next = b, b.previous = a, --i; - continue pack; - } - k = k.previous, sk += k._.r; - } - } while (j !== k.next); + m.clipExtent = function(_) { + if (!arguments.length) return clipAuto ? null : clipExtent(); + if (clipAuto = _ == null) { + var k = pi$3 * scale(), + t = translate(); + _ = [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]]; } + clipExtent(_); + return m; + }; - // Success! Insert the new circle c between a and b. - c.previous = a, c.next = b, a.next = b.previous = b = c; + return m.clipExtent(null); +} - // Update the weighted centroid. - oa += ca = c._.r * c._.r; - ox += ca * c._.x; - oy += ca * c._.y; +function tany(y) { + return tan((halfPi$2 + y) / 2); +} - // Compute the new closest circle a to centroid. - aa = distance2(a._, cx = ox / oa, cy = oy / oa); - while ((c = c.next) !== b) { - if ((ca = distance2(c._, cx, cy)) < aa) { - a = c, aa = ca; - } - } - b = a.next; - } +function conicConformalRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)), + f = cy0 * pow(tany(y0), n) / n; - // Compute the enclosing circle of the front chain. - a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); + if (!n) return mercatorRaw; - // Translate the circles to put the enclosing circle around the origin. - for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; + function project(x, y) { + if (f > 0) { if (y < -halfPi$2 + epsilon$2) y = -halfPi$2 + epsilon$2; } + else { if (y > halfPi$2 - epsilon$2) y = halfPi$2 - epsilon$2; } + var r = f / pow(tany(y), n); + return [r * sin$1(n * x), f - r * cos$1(n * x)]; + } - return c.r; + project.invert = function(x, y) { + var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy); + return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi$2]; + }; + + return project; } -var siblings = function(circles) { - packEnclose(circles); - return circles; +var conicConformal = function() { + return conicProjection(conicConformalRaw) + .scale(109.5) + .parallels([30, 30]); }; -function optional(f) { - return f == null ? null : required(f); -} - -function required(f) { - if (typeof f !== "function") throw new Error; - return f; +function equirectangularRaw(lambda, phi) { + return [lambda, phi]; } -function constantZero() { - return 0; -} +equirectangularRaw.invert = equirectangularRaw; -var constant$6 = function(x) { - return function() { - return x; - }; +var equirectangular = function() { + return projection(equirectangularRaw) + .scale(152.63); }; -function defaultRadius(d) { - return Math.sqrt(d.value); -} +function conicEquidistantRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0), + g = cy0 / n + y0; -var index = function() { - var radius = null, - dx = 1, - dy = 1, - padding = constantZero; + if (abs(n) < epsilon$2) return equirectangularRaw; - function pack(root) { - root.x = dx / 2, root.y = dy / 2; - if (radius) { - root.eachBefore(radiusLeaf(radius)) - .eachAfter(packChildren(padding, 0.5)) - .eachBefore(translateChild(1)); - } else { - root.eachBefore(radiusLeaf(defaultRadius)) - .eachAfter(packChildren(constantZero, 1)) - .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) - .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); - } - return root; + function project(x, y) { + var gy = g - y, nx = n * x; + return [gy * sin$1(nx), g - gy * cos$1(nx)]; } - pack.radius = function(x) { - return arguments.length ? (radius = optional(x), pack) : radius; - }; - - pack.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; + project.invert = function(x, y) { + var gy = g - y; + return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)]; }; - pack.padding = function(x) { - return arguments.length ? (padding = typeof x === "function" ? x : constant$6(+x), pack) : padding; - }; + return project; +} - return pack; +var conicEquidistant = function() { + return conicProjection(conicEquidistantRaw) + .scale(131.154) + .center([0, 13.9389]); }; -function radiusLeaf(radius) { - return function(node) { - if (!node.children) { - node.r = Math.max(0, +radius(node) || 0); - } - }; +function gnomonicRaw(x, y) { + var cy = cos$1(y), k = cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; } -function packChildren(padding, k) { - return function(node) { - if (children = node.children) { - var children, - i, - n = children.length, - r = padding(node) * k || 0, - e; +gnomonicRaw.invert = azimuthalInvert(atan); - if (r) for (i = 0; i < n; ++i) children[i].r += r; - e = packEnclose(children); - if (r) for (i = 0; i < n; ++i) children[i].r -= r; - node.r = e + r; +var gnomonic = function() { + return projection(gnomonicRaw) + .scale(144.049) + .clipAngle(60); +}; + +function scaleTranslate(kx, ky, tx, ty) { + return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$4 : transformer({ + point: function(x, y) { + this.stream.point(x * kx + tx, y * ky + ty); } - }; + }); } -function translateChild(k) { - return function(node) { - var parent = node.parent; - node.r *= k; - if (parent) { - node.x = parent.x + k * node.x; - node.y = parent.y + k * node.y; +var identity$5 = function() { + var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform = identity$4, // scale, translate and reflect + x0 = null, y0, x1, y1, clip = identity$4, // clip extent + cache, + cacheStream, + projection; + + function reset() { + cache = cacheStream = null; + return projection; + } + + return projection = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream)); + }, + clipExtent: function(_) { + return arguments.length ? (clip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }, + scale: function(_) { + return arguments.length ? (transform = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k; + }, + translate: function(_) { + return arguments.length ? (transform = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty]; + }, + reflectX: function(_) { + return arguments.length ? (transform = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0; + }, + reflectY: function(_) { + return arguments.length ? (transform = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0; + }, + fitExtent: function(extent, object) { + return fitExtent(projection, extent, object); + }, + fitSize: function(size, object) { + return fitSize(projection, size, object); } }; +}; + +function orthographicRaw(x, y) { + return [cos$1(y) * sin$1(x), sin$1(y)]; } -var roundNode = function(node) { - node.x0 = Math.round(node.x0); - node.y0 = Math.round(node.y0); - node.x1 = Math.round(node.x1); - node.y1 = Math.round(node.y1); +orthographicRaw.invert = azimuthalInvert(asin); + +var orthographic = function() { + return projection(orthographicRaw) + .scale(249.5) + .clipAngle(90 + epsilon$2); }; -var treemapDice = function(parent, x0, y0, x1, y1) { - var nodes = parent.children, - node, - i = -1, - n = nodes.length, - k = parent.value && (x1 - x0) / parent.value; +function stereographicRaw(x, y) { + var cy = cos$1(y), k = 1 + cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; +} - while (++i < n) { - node = nodes[i], node.y0 = y0, node.y1 = y1; - node.x0 = x0, node.x1 = x0 += node.value * k; - } +stereographicRaw.invert = azimuthalInvert(function(z) { + return 2 * atan(z); +}); + +var stereographic = function() { + return projection(stereographicRaw) + .scale(250) + .clipAngle(142); }; -var partition = function() { - var dx = 1, - dy = 1, - padding = 0, - round = false; - - function partition(root) { - var n = root.height + 1; - root.x0 = - root.y0 = padding; - root.x1 = dx; - root.y1 = dy / n; - root.eachBefore(positionNode(dy, n)); - if (round) root.eachBefore(roundNode); - return root; - } +function transverseMercatorRaw(lambda, phi) { + return [log(tan((halfPi$2 + phi) / 2)), -lambda]; +} - function positionNode(dy, n) { - return function(node) { - if (node.children) { - treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); - } - var x0 = node.x0, - y0 = node.y0, - x1 = node.x1 - padding, - y1 = node.y1 - padding; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - node.x0 = x0; - node.y0 = y0; - node.x1 = x1; - node.y1 = y1; - }; - } +transverseMercatorRaw.invert = function(x, y) { + return [-y, 2 * atan(exp(x)) - halfPi$2]; +}; - partition.round = function(x) { - return arguments.length ? (round = !!x, partition) : round; - }; +var transverseMercator = function() { + var m = mercatorProjection(transverseMercatorRaw), + center = m.center, + rotate = m.rotate; - partition.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; + m.center = function(_) { + return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); }; - partition.padding = function(x) { - return arguments.length ? (padding = +x, partition) : padding; + m.rotate = function(_) { + return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); }; - return partition; + return rotate([0, 0, 90]) + .scale(159.155); }; -var keyPrefix$1 = "$"; -var preroot = {depth: -1}; -var ambiguous = {}; +function defaultSeparation(a, b) { + return a.parent === b.parent ? 1 : 2; +} -function defaultId(d) { - return d.id; +function meanX(children) { + return children.reduce(meanXReduce, 0) / children.length; } -function defaultParentId(d) { - return d.parentId; +function meanXReduce(x, c) { + return x + c.x; } -var stratify = function() { - var id = defaultId, - parentId = defaultParentId; +function maxY(children) { + return 1 + children.reduce(maxYReduce, 0); +} - function stratify(data) { - var d, - i, - n = data.length, - root, - parent, - node, - nodes = new Array(n), - nodeId, - nodeKey, - nodeByKey = {}; +function maxYReduce(y, c) { + return Math.max(y, c.y); +} - for (i = 0; i < n; ++i) { - d = data[i], node = nodes[i] = new Node(d); - if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { - nodeKey = keyPrefix$1 + (node.id = nodeId); - nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; - } - } +function leafLeft(node) { + var children; + while (children = node.children) node = children[0]; + return node; +} - for (i = 0; i < n; ++i) { - node = nodes[i], nodeId = parentId(data[i], i, data); - if (nodeId == null || !(nodeId += "")) { - if (root) throw new Error("multiple roots"); - root = node; +function leafRight(node) { + var children; + while (children = node.children) node = children[children.length - 1]; + return node; +} + +var cluster = function() { + var separation = defaultSeparation, + dx = 1, + dy = 1, + nodeSize = false; + + function cluster(root) { + var previousNode, + x = 0; + + // First walk, computing the initial x & y values. + root.eachAfter(function(node) { + var children = node.children; + if (children) { + node.x = meanX(children); + node.y = maxY(children); } else { - parent = nodeByKey[keyPrefix$1 + nodeId]; - if (!parent) throw new Error("missing: " + nodeId); - if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); - if (parent.children) parent.children.push(node); - else parent.children = [node]; - node.parent = parent; + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; } - } + }); - if (!root) throw new Error("no root"); - root.parent = preroot; - root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); - root.parent = null; - if (n > 0) throw new Error("cycle"); + var left = leafLeft(root), + right = leafRight(root), + x0 = left.x - separation(left, right) / 2, + x1 = right.x + separation(right, left) / 2; - return root; + // Second walk, normalizing x & y to the desired size. + return root.eachAfter(nodeSize ? function(node) { + node.x = (node.x - root.x) * dx; + node.y = (root.y - node.y) * dy; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * dx; + node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; + }); } - stratify.id = function(x) { - return arguments.length ? (id = required(x), stratify) : id; + cluster.separation = function(x) { + return arguments.length ? (separation = x, cluster) : separation; }; - stratify.parentId = function(x) { - return arguments.length ? (parentId = required(x), stratify) : parentId; + cluster.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); }; - return stratify; + cluster.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); + }; + + return cluster; }; -function defaultSeparation$1(a, b) { - return a.parent === b.parent ? 1 : 2; -} +var node_each = function(callback) { + var node = this, current, next = [node], children, i, n; + do { + current = next.reverse(), next = []; + while (node = current.pop()) { + callback(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + next.push(children[i]); + } + } + } while (next.length); + return this; +}; -// function radialSeparation(a, b) { -// return (a.parent === b.parent ? 1 : 2) / a.depth; -// } +var node_eachBefore = function(callback) { + var node = this, nodes = [node], children, i; + while (node = nodes.pop()) { + callback(node), children = node.children; + if (children) for (i = children.length - 1; i >= 0; --i) { + nodes.push(children[i]); + } + } + return this; +}; -// This function is used to traverse the left contour of a subtree (or -// subforest). It returns the successor of v on this contour. This successor is -// either given by the leftmost child of v or by the thread of v. The function -// returns null if and only if v is on the highest level of its subtree. -function nextLeft(v) { - var children = v.children; - return children ? children[0] : v.t; -} +var node_eachAfter = function(callback) { + var node = this, nodes = [node], next = [], children, i, n; + while (node = nodes.pop()) { + next.push(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + nodes.push(children[i]); + } + } + while (node = next.pop()) { + callback(node); + } + return this; +}; -// This function works analogously to nextLeft. -function nextRight(v) { - var children = v.children; - return children ? children[children.length - 1] : v.t; -} +var node_sum = function(value) { + return this.eachAfter(function(node) { + var sum = +value(node.data) || 0, + children = node.children, + i = children && children.length; + while (--i >= 0) sum += children[i].value; + node.value = sum; + }); +}; + +var node_sort = function(compare) { + return this.eachBefore(function(node) { + if (node.children) { + node.children.sort(compare); + } + }); +}; + +var node_path = function(end) { + var start = this, + ancestor = leastCommonAncestor(start, end), + nodes = [start]; + while (start !== ancestor) { + start = start.parent; + nodes.push(start); + } + var k = nodes.length; + while (end !== ancestor) { + nodes.splice(k, 0, end); + end = end.parent; + } + return nodes; +}; -// Shifts the current subtree rooted at w+. This is done by increasing -// prelim(w+) and mod(w+) by shift. -function moveSubtree(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 leastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = a.ancestors(), + bNodes = b.ancestors(), + c = null; + a = aNodes.pop(); + b = bNodes.pop(); + while (a === b) { + c = a; + a = aNodes.pop(); + b = bNodes.pop(); + } + return c; } -// All other shifts, applied to the smaller subtrees between w- and w+, are -// performed by this function. To prepare the shifts, we have to adjust -// change(w+), shift(w+), and change(w-). -function executeShifts(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); +var node_ancestors = function() { + var node = this, nodes = [node]; + while (node = node.parent) { + nodes.push(node); } -} + return nodes; +}; -// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, -// returns the specified (default) ancestor. -function nextAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; -} +var node_descendants = function() { + var nodes = []; + this.each(function(node) { + nodes.push(node); + }); + return nodes; +}; -function TreeNode(node, i) { - this._ = node; - this.parent = null; - this.children = null; - this.A = null; // default ancestor - this.a = this; // ancestor - this.z = 0; // prelim - this.m = 0; // mod - this.c = 0; // change - this.s = 0; // shift - this.t = null; // thread - this.i = i; // number -} +var node_leaves = function() { + var leaves = []; + this.eachBefore(function(node) { + if (!node.children) { + leaves.push(node); + } + }); + return leaves; +}; -TreeNode.prototype = Object.create(Node.prototype); +var node_links = function() { + var root = this, links = []; + root.each(function(node) { + if (node !== root) { // Don’t include the root’s parent, if any. + links.push({source: node.parent, target: node}); + } + }); + return links; +}; -function treeRoot(root) { - var tree = new TreeNode(root, 0), +function hierarchy(data, children) { + var root = new Node(data), + valued = +data.value && (root.value = data.value), node, - nodes = [tree], + nodes = [root], child, - children, + childs, i, n; + if (children == null) children = defaultChildren; + while (node = nodes.pop()) { - if (children = node._.children) { - node.children = new Array(n = children.length); + if (valued) node.value = +node.data.value; + if ((childs = children(node.data)) && (n = childs.length)) { + node.children = new Array(n); for (i = n - 1; i >= 0; --i) { - nodes.push(child = node.children[i] = new TreeNode(children[i], i)); + nodes.push(child = node.children[i] = new Node(childs[i])); child.parent = node; + child.depth = node.depth + 1; } } } - (tree.parent = new TreeNode(null, 0)).children = [tree]; - return tree; + return root.eachBefore(computeHeight); } -// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm -var tree = function() { - var separation = defaultSeparation$1, - dx = 1, - dy = 1, - nodeSize = null; +function node_copy() { + return hierarchy(this).eachBefore(copyData); +} - function tree(root) { - var t = treeRoot(root); +function defaultChildren(d) { + return d.children; +} - // Compute the layout using Buchheim et al.’s algorithm. - t.eachAfter(firstWalk), t.parent.m = -t.z; - t.eachBefore(secondWalk); +function copyData(node) { + node.data = node.data.data; +} - // If a fixed node size is specified, scale x and y. - if (nodeSize) root.eachBefore(sizeNode); +function computeHeight(node) { + var height = 0; + do node.height = height; + while ((node = node.parent) && (node.height < ++height)); +} - // If a fixed tree size is specified, scale x and y based on the extent. - // Compute the left-most, right-most, and depth-most nodes for extents. - else { - var left = root, - right = root, - bottom = root; - root.eachBefore(function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var s = left === right ? 1 : separation(left, right) / 2, - tx = s - left.x, - kx = dx / (right.x + s + tx), - ky = dy / (bottom.depth || 1); - root.eachBefore(function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } +function Node(data) { + this.data = data; + this.depth = + this.height = 0; + this.parent = null; +} - return root; +Node.prototype = hierarchy.prototype = { + constructor: Node, + each: node_each, + eachAfter: node_eachAfter, + eachBefore: node_eachBefore, + sum: node_sum, + sort: node_sort, + path: node_path, + ancestors: node_ancestors, + descendants: node_descendants, + leaves: node_leaves, + links: node_links, + copy: node_copy +}; + +function Node$2(value) { + this._ = value; + this.next = null; +} + +var shuffle$1 = function(array) { + var i, + n = (array = array.slice()).length, + head = null, + node = head; + + while (n) { + var next = new Node$2(array[n - 1]); + if (node) node = node.next = next; + else node = head = next; + array[i] = array[--n]; } - // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is - // applied recursively to the children of v, as well as the function - // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the - // node v is placed to the midpoint of its outermost children. - function firstWalk(v) { - var children = v.children, - siblings = v.parent.children, - w = v.i ? siblings[v.i - 1] : null; - if (children) { - executeShifts(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]); + return { + head: head, + tail: node + }; +}; + +var enclose = function(circles) { + return encloseN(shuffle$1(circles), []); +}; + +function encloses(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r - b.r; + return dr * dr + 1e-6 > dx * dx + dy * dy; +} + +// Returns the smallest circle that contains circles L and intersects circles B. +function encloseN(L, B) { + var circle, + l0 = null, + l1 = L.head, + l2, + p1; + + switch (B.length) { + case 1: circle = enclose1(B[0]); break; + case 2: circle = enclose2(B[0], B[1]); break; + case 3: circle = enclose3(B[0], B[1], B[2]); break; } - // Computes all real x-coordinates by summing up the modifiers recursively. - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } + while (l1) { + p1 = l1._, l2 = l1.next; + if (!circle || !encloses(circle, p1)) { + + // Temporarily truncate L before l1. + if (l0) L.tail = l0, l0.next = null; + else L.head = L.tail = null; + + B.push(p1); + circle = encloseN(L, B); // Note: reorders L! + B.pop(); - // The core of the algorithm. Here, a new subtree is combined with the - // previous subtrees. Threads are used to traverse the inside and outside - // contours of the left and right subtree up to the highest common level. The - // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the - // superscript o means outside and i means inside, the subscript - means left - // subtree and + means right subtree. For summing up the modifiers along the - // contour, we use respective variables si+, si-, so-, and so+. Whenever two - // nodes of the inside contours conflict, we compute the left one of the - // greatest uncommon ancestors using the function ANCESTOR and call MOVE - // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. - // Finally, we add a new thread (if necessary). - 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 = nextRight(vim), vip = nextLeft(vip), vim && vip) { - vom = nextLeft(vom); - vop = nextRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - moveSubtree(nextAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !nextRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !nextLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } + // Move l1 to the front of L and reconnect the truncated list L. + if (L.head) l1.next = L.head, L.head = l1; + else l1.next = null, L.head = L.tail = l1; + l0 = L.tail, l0.next = l2; + + } else { + l0 = l1; } - return ancestor; + l1 = l2; } - function sizeNode(node) { - node.x *= dx; - node.y = node.depth * dy; - } + L.tail = l0; + return circle; +} - tree.separation = function(x) { - return arguments.length ? (separation = x, tree) : separation; +function enclose1(a) { + return { + x: a.x, + y: a.y, + r: a.r }; +} - tree.size = function(x) { - return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); +function enclose2(a, b) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, + l = Math.sqrt(x21 * x21 + y21 * y21); + return { + x: (x1 + x2 + x21 / l * r21) / 2, + y: (y1 + y2 + y21 / l * r21) / 2, + r: (l + r1 + r2) / 2 }; +} - tree.nodeSize = function(x) { - return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); +function enclose3(a, b, c) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x3 = c.x, y3 = c.y, r3 = c.r, + a2 = 2 * (x1 - x2), + b2 = 2 * (y1 - y2), + c2 = 2 * (r2 - r1), + d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2, + a3 = 2 * (x1 - x3), + b3 = 2 * (y1 - y3), + c3 = 2 * (r3 - r1), + d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3, + ab = a3 * b2 - a2 * b3, + xa = (b2 * d3 - b3 * d2) / ab - x1, + xb = (b3 * c2 - b2 * c3) / ab, + ya = (a3 * d2 - a2 * d3) / ab - y1, + yb = (a2 * c3 - a3 * c2) / ab, + A = xb * xb + yb * yb - 1, + B = 2 * (xa * xb + ya * yb + r1), + C = xa * xa + ya * ya - r1 * r1, + r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A); + return { + x: xa + xb * r + x1, + y: ya + yb * r + y1, + r: r }; +} - return tree; -}; +function place(a, b, c) { + var ax = a.x, + ay = a.y, + da = b.r + c.r, + db = a.r + c.r, + dx = b.x - ax, + dy = b.y - ay, + dc = dx * dx + dy * dy; + if (dc) { + var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), + y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = ax + x * dx + y * dy; + c.y = ay + x * dy - y * dx; + } else { + c.x = ax + db; + c.y = ay; + } +} -var treemapSlice = function(parent, x0, y0, x1, y1) { - var nodes = parent.children, - node, - i = -1, - n = nodes.length, - k = parent.value && (y1 - y0) / parent.value; +function intersects(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r + b.r; + return dr * dr > dx * dx + dy * dy; +} - while (++i < n) { - node = nodes[i], node.x0 = x0, node.x1 = x1; - node.y0 = y0, node.y1 = y0 += node.value * k; - } -}; +function distance2(circle, x, y) { + var dx = circle.x - x, + dy = circle.y - y; + return dx * dx + dy * dy; +} -var phi = (1 + Math.sqrt(5)) / 2; +function Node$1(circle) { + this._ = circle; + this.next = null; + this.previous = null; +} -function squarifyRatio(ratio, parent, x0, y0, x1, y1) { - var rows = [], - nodes = parent.children, - row, - nodeValue, - i0 = 0, - i1, - n = nodes.length, - dx, dy, - value = parent.value, - sumValue, - minValue, - maxValue, - newRatio, - minRatio, - alpha, - beta; +function packEnclose(circles) { + if (!(n = circles.length)) return 0; - while (i0 < n) { - dx = x1 - x0, dy = y1 - y0; - minValue = maxValue = sumValue = nodes[i0].value; - alpha = Math.max(dy / dx, dx / dy) / (value * ratio); - beta = sumValue * sumValue * alpha; - minRatio = Math.max(maxValue / beta, beta / minValue); + var a, b, c, n; - // Keep adding nodes while the aspect ratio maintains or improves. - for (i1 = i0 + 1; i1 < n; ++i1) { - sumValue += nodeValue = nodes[i1].value; - if (nodeValue < minValue) minValue = nodeValue; - if (nodeValue > maxValue) maxValue = nodeValue; - beta = sumValue * sumValue * alpha; - newRatio = Math.max(maxValue / beta, beta / minValue); - if (newRatio > minRatio) { sumValue -= nodeValue; break; } - minRatio = newRatio; + // Place the first circle. + a = circles[0], a.x = 0, a.y = 0; + if (!(n > 1)) return a.r; + + // Place the second circle. + b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; + if (!(n > 2)) return a.r + b.r; + + // Place the third circle. + place(b, a, c = circles[2]); + + // Initialize the weighted centroid. + var aa = a.r * a.r, + ba = b.r * b.r, + ca = c.r * c.r, + oa = aa + ba + ca, + ox = aa * a.x + ba * b.x + ca * c.x, + oy = aa * a.y + ba * b.y + ca * c.y, + cx, cy, i, j, k, sj, sk; + + // Initialize the front-chain using the first three circles a, b and c. + a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); + a.next = c.previous = b; + b.next = a.previous = c; + c.next = b.previous = a; + + // Attempt to place each remaining circle… + pack: for (i = 3; i < n; ++i) { + place(a._, b._, c = circles[i]), c = new Node$1(c); + + // If there are only three elements in the front-chain… + if ((k = a.previous) === (j = b.next)) { + // If the new circle intersects the third circle, + // rotate the front chain to try the next position. + if (intersects(j._, c._)) { + a = b, b = j, --i; + continue pack; + } + } + + // Find the closest intersecting circle on the front-chain, if any. + else { + sj = j._.r, sk = k._.r; + do { + if (sj <= sk) { + if (intersects(j._, c._)) { + b = j, a.next = b, b.previous = a, --i; + continue pack; + } + j = j.next, sj += j._.r; + } else { + if (intersects(k._, c._)) { + a = k, a.next = b, b.previous = a, --i; + continue pack; + } + k = k.previous, sk += k._.r; + } + } while (j !== k.next); } - // Position and record the row orientation. - rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); - if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); - else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); - value -= sumValue, i0 = i1; - } - - return rows; -} + // Success! Insert the new circle c between a and b. + c.previous = a, c.next = b, a.next = b.previous = b = c; -var squarify = (function custom(ratio) { + // Update the weighted centroid. + oa += ca = c._.r * c._.r; + ox += ca * c._.x; + oy += ca * c._.y; - function squarify(parent, x0, y0, x1, y1) { - squarifyRatio(ratio, parent, x0, y0, x1, y1); + // Compute the new closest circle a to centroid. + aa = distance2(a._, cx = ox / oa, cy = oy / oa); + while ((c = c.next) !== b) { + if ((ca = distance2(c._, cx, cy)) < aa) { + a = c, aa = ca; + } + } + b = a.next; } - squarify.ratio = function(x) { - return custom((x = +x) > 1 ? x : 1); - }; - - return squarify; -})(phi); + // Compute the enclosing circle of the front chain. + a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); -var index$1 = function() { - var tile = squarify, - round = false, - dx = 1, - dy = 1, - paddingStack = [0], - paddingInner = constantZero, - paddingTop = constantZero, - paddingRight = constantZero, - paddingBottom = constantZero, - paddingLeft = constantZero; + // Translate the circles to put the enclosing circle around the origin. + for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; - function treemap(root) { - root.x0 = - root.y0 = 0; - root.x1 = dx; - root.y1 = dy; - root.eachBefore(positionNode); - paddingStack = [0]; - if (round) root.eachBefore(roundNode); - return root; - } + return c.r; +} - function positionNode(node) { - var p = paddingStack[node.depth], - x0 = node.x0 + p, - y0 = node.y0 + p, - x1 = node.x1 - p, - y1 = node.y1 - p; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - node.x0 = x0; - node.y0 = y0; - node.x1 = x1; - node.y1 = y1; - if (node.children) { - p = paddingStack[node.depth + 1] = paddingInner(node) / 2; - x0 += paddingLeft(node) - p; - y0 += paddingTop(node) - p; - x1 -= paddingRight(node) - p; - y1 -= paddingBottom(node) - p; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - tile(node, x0, y0, x1, y1); - } - } +var siblings = function(circles) { + packEnclose(circles); + return circles; +}; - treemap.round = function(x) { - return arguments.length ? (round = !!x, treemap) : round; - }; +function optional(f) { + return f == null ? null : required(f); +} - treemap.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; - }; +function required(f) { + if (typeof f !== "function") throw new Error; + return f; +} - treemap.tile = function(x) { - return arguments.length ? (tile = required(x), treemap) : tile; - }; +function constantZero() { + return 0; +} - treemap.padding = function(x) { - return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); +var constant$8 = function(x) { + return function() { + return x; }; +}; - treemap.paddingInner = function(x) { - return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$6(+x), treemap) : paddingInner; - }; +function defaultRadius$1(d) { + return Math.sqrt(d.value); +} - treemap.paddingOuter = function(x) { - return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); - }; +var index$2 = function() { + var radius = null, + dx = 1, + dy = 1, + padding = constantZero; - treemap.paddingTop = function(x) { - return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$6(+x), treemap) : paddingTop; - }; + function pack(root) { + root.x = dx / 2, root.y = dy / 2; + if (radius) { + root.eachBefore(radiusLeaf(radius)) + .eachAfter(packChildren(padding, 0.5)) + .eachBefore(translateChild(1)); + } else { + root.eachBefore(radiusLeaf(defaultRadius$1)) + .eachAfter(packChildren(constantZero, 1)) + .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) + .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); + } + return root; + } - treemap.paddingRight = function(x) { - return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$6(+x), treemap) : paddingRight; + pack.radius = function(x) { + return arguments.length ? (radius = optional(x), pack) : radius; }; - treemap.paddingBottom = function(x) { - return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$6(+x), treemap) : paddingBottom; + pack.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; }; - treemap.paddingLeft = function(x) { - return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$6(+x), treemap) : paddingLeft; + pack.padding = function(x) { + return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding; }; - return treemap; + return pack; }; -var binary = function(parent, x0, y0, x1, y1) { - var nodes = parent.children, - i, n = nodes.length, - sum, sums = new Array(n + 1); - - for (sums[0] = sum = i = 0; i < n; ++i) { - sums[i + 1] = sum += nodes[i].value; - } - - partition(0, n, parent.value, x0, y0, x1, y1); - - function partition(i, j, value, x0, y0, x1, y1) { - if (i >= j - 1) { - var node = nodes[i]; - node.x0 = x0, node.y0 = y0; - node.x1 = x1, node.y1 = y1; - return; - } - - var valueOffset = sums[i], - valueTarget = (value / 2) + valueOffset, - k = i + 1, - hi = j - 1; - - while (k < hi) { - var mid = k + hi >>> 1; - if (sums[mid] < valueTarget) k = mid + 1; - else hi = mid; - } - - var valueLeft = sums[k] - valueOffset, - valueRight = value - valueLeft; - - if ((y1 - y0) > (x1 - x0)) { - var yk = (y0 * valueRight + y1 * valueLeft) / value; - partition(i, k, valueLeft, x0, y0, x1, yk); - partition(k, j, valueRight, x0, yk, x1, y1); - } else { - var xk = (x0 * valueRight + x1 * valueLeft) / value; - partition(i, k, valueLeft, x0, y0, xk, y1); - partition(k, j, valueRight, xk, y0, x1, y1); +function radiusLeaf(radius) { + return function(node) { + if (!node.children) { + node.r = Math.max(0, +radius(node) || 0); } - } -}; - -var sliceDice = function(parent, x0, y0, x1, y1) { - (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); -}; - -var resquarify = (function custom(ratio) { + }; +} - function resquarify(parent, x0, y0, x1, y1) { - if ((rows = parent._squarify) && (rows.ratio === ratio)) { - var rows, - row, - nodes, +function packChildren(padding, k) { + return function(node) { + if (children = node.children) { + var children, i, - j = -1, - n, - m = rows.length, - value = parent.value; + n = children.length, + r = padding(node) * k || 0, + e; - while (++j < m) { - row = rows[j], nodes = row.children; - for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; - if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); - else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); - value -= row.value; - } - } else { - parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); - rows.ratio = ratio; + if (r) for (i = 0; i < n; ++i) children[i].r += r; + e = packEnclose(children); + if (r) for (i = 0; i < n; ++i) children[i].r -= r; + node.r = e + r; } - } + }; +} - resquarify.ratio = function(x) { - return custom((x = +x) > 1 ? x : 1); +function translateChild(k) { + return function(node) { + var parent = node.parent; + node.r *= k; + if (parent) { + node.x = parent.x + k * node.x; + node.y = parent.y + k * node.y; + } }; +} - return resquarify; -})(phi); +var roundNode = function(node) { + node.x0 = Math.round(node.x0); + node.y0 = Math.round(node.y0); + node.x1 = Math.round(node.x1); + node.y1 = Math.round(node.y1); +}; -var center$1 = function(x, y) { - var nodes; +var treemapDice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (x1 - x0) / parent.value; - if (x == null) x = 0; - if (y == null) y = 0; + while (++i < n) { + node = nodes[i], node.y0 = y0, node.y1 = y1; + node.x0 = x0, node.x1 = x0 += node.value * k; + } +}; - function force() { - var i, - n = nodes.length, - node, - sx = 0, - sy = 0; +var partition = function() { + var dx = 1, + dy = 1, + padding = 0, + round = false; - for (i = 0; i < n; ++i) { - node = nodes[i], sx += node.x, sy += node.y; - } + function partition(root) { + var n = root.height + 1; + root.x0 = + root.y0 = padding; + root.x1 = dx; + root.y1 = dy / n; + root.eachBefore(positionNode(dy, n)); + if (round) root.eachBefore(roundNode); + return root; + } - for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { - node = nodes[i], node.x -= sx, node.y -= sy; - } + function positionNode(dy, n) { + return function(node) { + if (node.children) { + treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); + } + var x0 = node.x0, + y0 = node.y0, + x1 = node.x1 - padding, + y1 = node.y1 - padding; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + }; } - force.initialize = function(_) { - nodes = _; + partition.round = function(x) { + return arguments.length ? (round = !!x, partition) : round; }; - force.x = function(_) { - return arguments.length ? (x = +_, force) : x; + partition.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; }; - force.y = function(_) { - return arguments.length ? (y = +_, force) : y; + partition.padding = function(x) { + return arguments.length ? (padding = +x, partition) : padding; }; - return force; -}; - -var constant$7 = function(x) { - return function() { - return x; - }; + return partition; }; -var jiggle = function() { - return (Math.random() - 0.5) * 1e-6; -}; +var keyPrefix$1 = "$"; +var preroot = {depth: -1}; +var ambiguous = {}; -function x$1(d) { - return d.x + d.vx; +function defaultId(d) { + return d.id; } -function y$1(d) { - return d.y + d.vy; +function defaultParentId(d) { + return d.parentId; } -var collide = function(radius) { - var nodes, - radii, - strength = 1, - iterations = 1; - - if (typeof radius !== "function") radius = constant$7(radius == null ? 1 : +radius); +var stratify = function() { + var id = defaultId, + parentId = defaultParentId; - function force() { - var i, n = nodes.length, - tree, + function stratify(data) { + var d, + i, + n = data.length, + root, + parent, node, - xi, - yi, - ri, - ri2; + nodes = new Array(n), + nodeId, + nodeKey, + nodeByKey = {}; - for (var k = 0; k < iterations; ++k) { - tree = quadtree(nodes, x$1, y$1).visitAfter(prepare); - for (i = 0; i < n; ++i) { - node = nodes[i]; - ri = radii[i], ri2 = ri * ri; - xi = node.x + node.vx; - yi = node.y + node.vy; - tree.visit(apply); + for (i = 0; i < n; ++i) { + d = data[i], node = nodes[i] = new Node(d); + if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { + nodeKey = keyPrefix$1 + (node.id = nodeId); + nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; } } - function apply(quad, x0, y0, x1, y1) { - var data = quad.data, rj = quad.r, r = ri + rj; - if (data) { - if (data.index > i) { - var x = xi - data.x - data.vx, - y = yi - data.y - data.vy, - l = x * x + y * y; - if (l < r * r) { - if (x === 0) x = jiggle(), l += x * x; - if (y === 0) y = jiggle(), l += y * y; - l = (r - (l = Math.sqrt(l))) / l * strength; - node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); - node.vy += (y *= l) * r; - data.vx -= x * (r = 1 - r); - data.vy -= y * r; - } - } - return; + for (i = 0; i < n; ++i) { + node = nodes[i], nodeId = parentId(data[i], i, data); + if (nodeId == null || !(nodeId += "")) { + if (root) throw new Error("multiple roots"); + root = node; + } else { + parent = nodeByKey[keyPrefix$1 + nodeId]; + if (!parent) throw new Error("missing: " + nodeId); + if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); + if (parent.children) parent.children.push(node); + else parent.children = [node]; + node.parent = parent; } - return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; } - } - function prepare(quad) { - if (quad.data) return quad.r = radii[quad.data.index]; - for (var i = quad.r = 0; i < 4; ++i) { - if (quad[i] && quad[i].r > quad.r) { - quad.r = quad[i].r; - } - } - } + if (!root) throw new Error("no root"); + root.parent = preroot; + root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); + root.parent = null; + if (n > 0) throw new Error("cycle"); - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - radii = new Array(n); - for (i = 0; i < n; ++i) radii[i] = +radius(nodes[i], i, nodes); + return root; } - force.initialize = function(_) { - nodes = _; - initialize(); + stratify.id = function(x) { + return arguments.length ? (id = required(x), stratify) : id; }; - force.iterations = function(_) { - return arguments.length ? (iterations = +_, force) : iterations; + stratify.parentId = function(x) { + return arguments.length ? (parentId = required(x), stratify) : parentId; }; - force.strength = function(_) { - return arguments.length ? (strength = +_, force) : strength; - }; + return stratify; +}; - force.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : radius; - }; +function defaultSeparation$1(a, b) { + return a.parent === b.parent ? 1 : 2; +} - return force; -}; +// function radialSeparation(a, b) { +// return (a.parent === b.parent ? 1 : 2) / a.depth; +// } -function index$2(d, i) { - return i; +// This function is used to traverse the left contour of a subtree (or +// subforest). It returns the successor of v on this contour. This successor is +// either given by the leftmost child of v or by the thread of v. The function +// returns null if and only if v is on the highest level of its subtree. +function nextLeft(v) { + var children = v.children; + return children ? children[0] : v.t; } -function find(nodeById, nodeId) { - var node = nodeById.get(nodeId); - if (!node) throw new Error("missing: " + nodeId); - return node; +// This function works analogously to nextLeft. +function nextRight(v) { + var children = v.children; + return children ? children[children.length - 1] : v.t; +} + +// Shifts the current subtree rooted at w+. This is done by increasing +// prelim(w+) and mod(w+) by shift. +function moveSubtree(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; +} + +// All other shifts, applied to the smaller subtrees between w- and w+, are +// performed by this function. To prepare the shifts, we have to adjust +// change(w+), shift(w+), and change(w-). +function executeShifts(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); + } +} + +// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, +// returns the specified (default) ancestor. +function nextAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; +} + +function TreeNode(node, i) { + this._ = node; + this.parent = null; + this.children = null; + this.A = null; // default ancestor + this.a = this; // ancestor + this.z = 0; // prelim + this.m = 0; // mod + this.c = 0; // change + this.s = 0; // shift + this.t = null; // thread + this.i = i; // number } -var link = function(links) { - var id = index$2, - strength = defaultStrength, - strengths, - distance = constant$7(30), - distances, - nodes, - count, - bias, - iterations = 1; - - if (links == null) links = []; +TreeNode.prototype = Object.create(Node.prototype); - function defaultStrength(link) { - return 1 / Math.min(count[link.source.index], count[link.target.index]); - } +function treeRoot(root) { + var tree = new TreeNode(root, 0), + node, + nodes = [tree], + child, + children, + i, + n; - function force(alpha) { - for (var k = 0, n = links.length; k < iterations; ++k) { - for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { - link = links[i], source = link.source, target = link.target; - x = target.x + target.vx - source.x - source.vx || jiggle(); - y = target.y + target.vy - source.y - source.vy || jiggle(); - l = Math.sqrt(x * x + y * y); - l = (l - distances[i]) / l * alpha * strengths[i]; - x *= l, y *= l; - target.vx -= x * (b = bias[i]); - target.vy -= y * b; - source.vx += x * (b = 1 - b); - source.vy += y * b; + while (node = nodes.pop()) { + if (children = node._.children) { + node.children = new Array(n = children.length); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new TreeNode(children[i], i)); + child.parent = node; } } } - function initialize() { - if (!nodes) return; + (tree.parent = new TreeNode(null, 0)).children = [tree]; + return tree; +} - var i, - n = nodes.length, - m = links.length, - nodeById = map$1(nodes, id), - link; +// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm +var tree = function() { + var separation = defaultSeparation$1, + dx = 1, + dy = 1, + nodeSize = null; - for (i = 0, count = new Array(n); i < n; ++i) { - count[i] = 0; - } + function tree(root) { + var t = treeRoot(root); - for (i = 0; i < m; ++i) { - link = links[i], link.index = i; - if (typeof link.source !== "object") link.source = find(nodeById, link.source); - if (typeof link.target !== "object") link.target = find(nodeById, link.target); - ++count[link.source.index], ++count[link.target.index]; - } + // Compute the layout using Buchheim et al.’s algorithm. + t.eachAfter(firstWalk), t.parent.m = -t.z; + t.eachBefore(secondWalk); - for (i = 0, bias = new Array(m); i < m; ++i) { - link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + // If a fixed node size is specified, scale x and y. + if (nodeSize) root.eachBefore(sizeNode); + + // If a fixed tree size is specified, scale x and y based on the extent. + // Compute the left-most, right-most, and depth-most nodes for extents. + else { + var left = root, + right = root, + bottom = root; + root.eachBefore(function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var s = left === right ? 1 : separation(left, right) / 2, + tx = s - left.x, + kx = dx / (right.x + s + tx), + ky = dy / (bottom.depth || 1); + root.eachBefore(function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); } - strengths = new Array(m), initializeStrength(); - distances = new Array(m), initializeDistance(); + return root; } - function initializeStrength() { - if (!nodes) return; - - for (var i = 0, n = links.length; i < n; ++i) { - strengths[i] = +strength(links[i], i, links); + // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is + // applied recursively to the children of v, as well as the function + // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the + // node v is placed to the midpoint of its outermost children. + function firstWalk(v) { + var children = v.children, + siblings = v.parent.children, + w = v.i ? siblings[v.i - 1] : null; + if (children) { + executeShifts(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]); } - function initializeDistance() { - if (!nodes) return; + // Computes all real x-coordinates by summing up the modifiers recursively. + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } - for (var i = 0, n = links.length; i < n; ++i) { - distances[i] = +distance(links[i], i, links); + // The core of the algorithm. Here, a new subtree is combined with the + // previous subtrees. Threads are used to traverse the inside and outside + // contours of the left and right subtree up to the highest common level. The + // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the + // superscript o means outside and i means inside, the subscript - means left + // subtree and + means right subtree. For summing up the modifiers along the + // contour, we use respective variables si+, si-, so-, and so+. Whenever two + // nodes of the inside contours conflict, we compute the left one of the + // greatest uncommon ancestors using the function ANCESTOR and call MOVE + // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. + // Finally, we add a new thread (if necessary). + 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 = nextRight(vim), vip = nextLeft(vip), vim && vip) { + vom = nextLeft(vom); + vop = nextRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + moveSubtree(nextAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !nextRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !nextLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } } + return ancestor; } - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.links = function(_) { - return arguments.length ? (links = _, initialize(), force) : links; - }; - - force.id = function(_) { - return arguments.length ? (id = _, force) : id; - }; + function sizeNode(node) { + node.x *= dx; + node.y = node.depth * dy; + } - force.iterations = function(_) { - return arguments.length ? (iterations = +_, force) : iterations; + tree.separation = function(x) { + return arguments.length ? (separation = x, tree) : separation; }; - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initializeStrength(), force) : strength; + tree.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); }; - force.distance = function(_) { - return arguments.length ? (distance = typeof _ === "function" ? _ : constant$7(+_), initializeDistance(), force) : distance; + tree.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); }; - return force; + return tree; }; -function x$2(d) { - return d.x; -} - -function y$2(d) { - return d.y; -} - -var initialRadius = 10; -var initialAngle = Math.PI * (3 - Math.sqrt(5)); - -var simulation = function(nodes) { - var simulation, - alpha = 1, - alphaMin = 0.001, - alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), - alphaTarget = 0, - velocityDecay = 0.6, - forces = map$1(), - stepper = timer(step), - event = dispatch("tick", "end"); - - if (nodes == null) nodes = []; +var treemapSlice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (y1 - y0) / parent.value; - function step() { - tick(); - event.call("tick", simulation); - if (alpha < alphaMin) { - stepper.stop(); - event.call("end", simulation); - } + while (++i < n) { + node = nodes[i], node.x0 = x0, node.x1 = x1; + node.y0 = y0, node.y1 = y0 += node.value * k; } +}; - function tick() { - var i, n = nodes.length, node; +var phi = (1 + Math.sqrt(5)) / 2; - alpha += (alphaTarget - alpha) * alphaDecay; +function squarifyRatio(ratio, parent, x0, y0, x1, y1) { + var rows = [], + nodes = parent.children, + row, + nodeValue, + i0 = 0, + i1 = 0, + n = nodes.length, + dx, dy, + value = parent.value, + sumValue, + minValue, + maxValue, + newRatio, + minRatio, + alpha, + beta; - forces.each(function(force) { - force(alpha); - }); + while (i0 < n) { + dx = x1 - x0, dy = y1 - y0; - for (i = 0; i < n; ++i) { - node = nodes[i]; - if (node.fx == null) node.x += node.vx *= velocityDecay; - else node.x = node.fx, node.vx = 0; - if (node.fy == null) node.y += node.vy *= velocityDecay; - else node.y = node.fy, node.vy = 0; - } - } + // Find the next non-empty node. + do sumValue = nodes[i1++].value; while (!sumValue && i1 < n); + minValue = maxValue = sumValue; + alpha = Math.max(dy / dx, dx / dy) / (value * ratio); + beta = sumValue * sumValue * alpha; + minRatio = Math.max(maxValue / beta, beta / minValue); - function initializeNodes() { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.index = i; - if (isNaN(node.x) || isNaN(node.y)) { - var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; - node.x = radius * Math.cos(angle); - node.y = radius * Math.sin(angle); - } - if (isNaN(node.vx) || isNaN(node.vy)) { - node.vx = node.vy = 0; - } + // Keep adding nodes while the aspect ratio maintains or improves. + for (; i1 < n; ++i1) { + sumValue += nodeValue = nodes[i1].value; + if (nodeValue < minValue) minValue = nodeValue; + if (nodeValue > maxValue) maxValue = nodeValue; + beta = sumValue * sumValue * alpha; + newRatio = Math.max(maxValue / beta, beta / minValue); + if (newRatio > minRatio) { sumValue -= nodeValue; break; } + minRatio = newRatio; } - } - function initializeForce(force) { - if (force.initialize) force.initialize(nodes); - return force; + // Position and record the row orientation. + rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); + if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); + else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); + value -= sumValue, i0 = i1; } - initializeNodes(); - - return simulation = { - tick: tick, - - restart: function() { - return stepper.restart(step), simulation; - }, + return rows; +} - stop: function() { - return stepper.stop(), simulation; - }, +var squarify = ((function custom(ratio) { - nodes: function(_) { - return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; - }, + function squarify(parent, x0, y0, x1, y1) { + squarifyRatio(ratio, parent, x0, y0, x1, y1); + } - alpha: function(_) { - return arguments.length ? (alpha = +_, simulation) : alpha; - }, + squarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; - alphaMin: function(_) { - return arguments.length ? (alphaMin = +_, simulation) : alphaMin; - }, + return squarify; +}))(phi); - alphaDecay: function(_) { - return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; - }, +var index$3 = function() { + var tile = squarify, + round = false, + dx = 1, + dy = 1, + paddingStack = [0], + paddingInner = constantZero, + paddingTop = constantZero, + paddingRight = constantZero, + paddingBottom = constantZero, + paddingLeft = constantZero; - alphaTarget: function(_) { - return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; - }, + function treemap(root) { + root.x0 = + root.y0 = 0; + root.x1 = dx; + root.y1 = dy; + root.eachBefore(positionNode); + paddingStack = [0]; + if (round) root.eachBefore(roundNode); + return root; + } - velocityDecay: function(_) { - return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; - }, + function positionNode(node) { + var p = paddingStack[node.depth], + x0 = node.x0 + p, + y0 = node.y0 + p, + x1 = node.x1 - p, + y1 = node.y1 - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + if (node.children) { + p = paddingStack[node.depth + 1] = paddingInner(node) / 2; + x0 += paddingLeft(node) - p; + y0 += paddingTop(node) - p; + x1 -= paddingRight(node) - p; + y1 -= paddingBottom(node) - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + tile(node, x0, y0, x1, y1); + } + } - force: function(name, _) { - return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); - }, + treemap.round = function(x) { + return arguments.length ? (round = !!x, treemap) : round; + }; - find: function(x, y, radius) { - var i = 0, - n = nodes.length, - dx, - dy, - d2, - node, - closest; + treemap.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; + }; - if (radius == null) radius = Infinity; - else radius *= radius; + treemap.tile = function(x) { + return arguments.length ? (tile = required(x), treemap) : tile; + }; - for (i = 0; i < n; ++i) { - node = nodes[i]; - dx = x - node.x; - dy = y - node.y; - d2 = dx * dx + dy * dy; - if (d2 < radius) closest = node, radius = d2; - } + treemap.padding = function(x) { + return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); + }; - return closest; - }, + treemap.paddingInner = function(x) { + return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$8(+x), treemap) : paddingInner; + }; - on: function(name, _) { - return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); - } + treemap.paddingOuter = function(x) { + return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); }; -}; -var manyBody = function() { - var nodes, - node, - alpha, - strength = constant$7(-30), - strengths, - distanceMin2 = 1, - distanceMax2 = Infinity, - theta2 = 0.81; + treemap.paddingTop = function(x) { + return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$8(+x), treemap) : paddingTop; + }; - function force(_) { - var i, n = nodes.length, tree = quadtree(nodes, x$2, y$2).visitAfter(accumulate); - for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); - } + treemap.paddingRight = function(x) { + return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$8(+x), treemap) : paddingRight; + }; - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - for (i = 0; i < n; ++i) strengths[i] = +strength(nodes[i], i, nodes); - } + treemap.paddingBottom = function(x) { + return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$8(+x), treemap) : paddingBottom; + }; - function accumulate(quad) { - var strength = 0, q, c, x$$1, y$$1, i; + treemap.paddingLeft = function(x) { + return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$8(+x), treemap) : paddingLeft; + }; - // For internal nodes, accumulate forces from child quadrants. - if (quad.length) { - for (x$$1 = y$$1 = i = 0; i < 4; ++i) { - if ((q = quad[i]) && (c = q.value)) { - strength += c, x$$1 += c * q.x, y$$1 += c * q.y; - } - } - quad.x = x$$1 / strength; - quad.y = y$$1 / strength; - } + return treemap; +}; - // For leaf nodes, accumulate forces from coincident quadrants. - else { - q = quad; - q.x = q.data.x; - q.y = q.data.y; - do strength += strengths[q.data.index]; - while (q = q.next); - } +var binary = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + i, n = nodes.length, + sum, sums = new Array(n + 1); - quad.value = strength; + for (sums[0] = sum = i = 0; i < n; ++i) { + sums[i + 1] = sum += nodes[i].value; } - function apply(quad, x1, _, x2) { - if (!quad.value) return true; + partition(0, n, parent.value, x0, y0, x1, y1); - var x$$1 = quad.x - node.x, - y$$1 = quad.y - node.y, - w = x2 - x1, - l = x$$1 * x$$1 + y$$1 * y$$1; + function partition(i, j, value, x0, y0, x1, y1) { + if (i >= j - 1) { + var node = nodes[i]; + node.x0 = x0, node.y0 = y0; + node.x1 = x1, node.y1 = y1; + return; + } - // Apply the Barnes-Hut approximation if possible. - // Limit forces for very close nodes; randomize direction if coincident. - if (w * w / theta2 < l) { - if (l < distanceMax2) { - if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; - if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); - node.vx += x$$1 * quad.value * alpha / l; - node.vy += y$$1 * quad.value * alpha / l; - } - return true; + var valueOffset = sums[i], + valueTarget = (value / 2) + valueOffset, + k = i + 1, + hi = j - 1; + + while (k < hi) { + var mid = k + hi >>> 1; + if (sums[mid] < valueTarget) k = mid + 1; + else hi = mid; } - // Otherwise, process points directly. - else if (quad.length || l >= distanceMax2) return; + var valueLeft = sums[k] - valueOffset, + valueRight = value - valueLeft; - // Limit forces for very close nodes; randomize direction if coincident. - if (quad.data !== node || quad.next) { - if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; - if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + if ((y1 - y0) > (x1 - x0)) { + var yk = (y0 * valueRight + y1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, x1, yk); + partition(k, j, valueRight, x0, yk, x1, y1); + } else { + var xk = (x0 * valueRight + x1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, xk, y1); + partition(k, j, valueRight, xk, y0, x1, y1); } - - do if (quad.data !== node) { - w = strengths[quad.data.index] * alpha / l; - node.vx += x$$1 * w; - node.vy += y$$1 * w; - } while (quad = quad.next); } +}; - force.initialize = function(_) { - nodes = _; - initialize(); - }; +var sliceDice = function(parent, x0, y0, x1, y1) { + (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); +}; - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; - }; +var resquarify = ((function custom(ratio) { - force.distanceMin = function(_) { - return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); - }; + function resquarify(parent, x0, y0, x1, y1) { + if ((rows = parent._squarify) && (rows.ratio === ratio)) { + var rows, + row, + nodes, + i, + j = -1, + n, + m = rows.length, + value = parent.value; - force.distanceMax = function(_) { - return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); - }; + while (++j < m) { + row = rows[j], nodes = row.children; + for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; + if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); + else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); + value -= row.value; + } + } else { + parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); + rows.ratio = ratio; + } + } - force.theta = function(_) { - return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + resquarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); }; - return force; -}; - -var x$3 = function(x) { - var strength = constant$7(0.1), - nodes, - strengths, - xz; + return resquarify; +}))(phi); - if (typeof x !== "function") x = constant$7(x == null ? 0 : +x); +var area$1 = function(polygon) { + var i = -1, + n = polygon.length, + a, + b = polygon[n - 1], + area = 0; - function force(alpha) { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; - } + while (++i < n) { + a = b; + b = polygon[i]; + area += a[1] * b[0] - a[0] * b[1]; } - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - xz = new Array(n); - for (i = 0; i < n; ++i) { - strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); - } - } + return area / 2; +}; - force.initialize = function(_) { - nodes = _; - initialize(); - }; +var centroid$1 = function(polygon) { + var i = -1, + n = polygon.length, + x = 0, + y = 0, + a, + b = polygon[n - 1], + c, + k = 0; - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; - }; + while (++i < n) { + a = b; + b = polygon[i]; + k += c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } - force.x = function(_) { - return arguments.length ? (x = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : x; - }; + return k *= 3, [x / k, y / k]; +}; - return force; +// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of +// the 3D cross product in a quadrant I Cartesian coordinate system (+x is +// right, +y is up). Returns a positive value if ABC is counter-clockwise, +// negative if clockwise, and zero if the points are collinear. +var cross = function(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); }; -var y$3 = function(y) { - var strength = constant$7(0.1), - nodes, - strengths, - yz; +function lexicographicOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; +} - if (typeof y !== "function") y = constant$7(y == null ? 0 : +y); +// Computes the upper convex hull per the monotone chain algorithm. +// Assumes points.length >= 3, is sorted by x, unique in y. +// Returns an array of indices into points in left-to-right order. +function computeUpperHullIndexes(points) { + var n = points.length, + indexes = [0, 1], + size = 2; - function force(alpha) { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; - } + for (var i = 2; i < n; ++i) { + while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; + indexes[size++] = i; } - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - yz = new Array(n); - for (i = 0; i < n; ++i) { - strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); - } - } + return indexes.slice(0, size); // remove popped points +} - force.initialize = function(_) { - nodes = _; - initialize(); - }; +var hull = function(points) { + if ((n = points.length) < 3) return null; - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; - }; + var i, + n, + sortedPoints = new Array(n), + flippedPoints = new Array(n); - force.y = function(_) { - return arguments.length ? (y = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : y; - }; + for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i]; + sortedPoints.sort(lexicographicOrder); + for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; - return force; -}; + var upperIndexes = computeUpperHullIndexes(sortedPoints), + lowerIndexes = computeUpperHullIndexes(flippedPoints); -function nopropagation() { - exports.event.stopImmediatePropagation(); -} + // Construct the hull polygon, removing possible duplicate endpoints. + var skipLeft = lowerIndexes[0] === upperIndexes[0], + skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], + hull = []; -var noevent = function() { - exports.event.preventDefault(); - exports.event.stopImmediatePropagation(); + // Add upper hull in right-to-l order. + // Then add lower hull in left-to-right order. + for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]); + for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); + + return hull; }; -var dragDisable = function(view) { - var root = view.document.documentElement, - selection$$1 = select(view).on("dragstart.drag", noevent, true); - if ("onselectstart" in root) { - selection$$1.on("selectstart.drag", noevent, true); - } else { - root.__noselect = root.style.MozUserSelect; - root.style.MozUserSelect = "none"; +var contains = function(polygon, point) { + var n = polygon.length, + p = polygon[n - 1], + x = point[0], y = point[1], + x0 = p[0], y0 = p[1], + x1, y1, + inside = false; + + for (var i = 0; i < n; ++i) { + p = polygon[i], x1 = p[0], y1 = p[1]; + if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside; + x0 = x1, y0 = y1; } + + return inside; }; -function yesdrag(view, noclick) { - var root = view.document.documentElement, - selection$$1 = select(view).on("dragstart.drag", null); - if (noclick) { - selection$$1.on("click.drag", noevent, true); - setTimeout(function() { selection$$1.on("click.drag", null); }, 0); - } - if ("onselectstart" in root) { - selection$$1.on("selectstart.drag", null); - } else { - root.style.MozUserSelect = root.__noselect; - delete root.__noselect; +var length$2 = function(polygon) { + var i = -1, + n = polygon.length, + b = polygon[n - 1], + xa, + ya, + xb = b[0], + yb = b[1], + perimeter = 0; + + while (++i < n) { + xa = xb; + ya = yb; + b = polygon[i]; + xb = b[0]; + yb = b[1]; + xa -= xb; + ya -= yb; + perimeter += Math.sqrt(xa * xa + ya * ya); } -} - -var constant$8 = function(x) { - return function() { - return x; - }; -}; - -function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) { - this.target = target; - this.type = type; - this.subject = subject; - this.identifier = id; - this.active = active; - this.x = x; - this.y = y; - this.dx = dx; - this.dy = dy; - this._ = dispatch; -} -DragEvent.prototype.on = function() { - var value = this._.on.apply(this._, arguments); - return value === this._ ? this : value; + return perimeter; }; -// Ignore right-click, since that should open the context menu. -function defaultFilter() { - return !exports.event.button; -} +var slice$3 = [].slice; -function defaultContainer() { - return this.parentNode; -} +var noabort = {}; -function defaultSubject(d) { - return d == null ? {x: exports.event.x, y: exports.event.y} : d; +function Queue(size) { + if (!(size >= 1)) throw new Error; + this._size = size; + this._call = + this._error = null; + this._tasks = []; + this._data = []; + this._waiting = + this._active = + this._ended = + this._start = 0; // inside a synchronous task callback? } -var drag = function() { - var filter = defaultFilter, - container = defaultContainer, - subject = defaultSubject, - gestures = {}, - listeners = dispatch("start", "drag", "end"), - active = 0, - mousemoving, - touchending; - - function drag(selection$$1) { - selection$$1 - .on("mousedown.drag", mousedowned) - .on("touchstart.drag", touchstarted) - .on("touchmove.drag", touchmoved) - .on("touchend.drag touchcancel.drag", touchended) - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); +Queue.prototype = queue.prototype = { + constructor: Queue, + defer: function(callback) { + if (typeof callback !== "function" || this._call) throw new Error; + if (this._error != null) return this; + var t = slice$3.call(arguments, 1); + t.push(callback); + ++this._waiting, this._tasks.push(t); + poke$1(this); + return this; + }, + abort: function() { + if (this._error == null) abort(this, new Error("abort")); + return this; + }, + await: function(callback) { + if (typeof callback !== "function" || this._call) throw new Error; + this._call = function(error, results) { callback.apply(null, [error].concat(results)); }; + maybeNotify(this); + return this; + }, + awaitAll: function(callback) { + if (typeof callback !== "function" || this._call) throw new Error; + this._call = callback; + maybeNotify(this); + return this; } +}; - function mousedowned() { - if (touchending || !filter.apply(this, arguments)) return; - var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments); - if (!gesture) return; - select(exports.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); - dragDisable(exports.event.view); - nopropagation(); - mousemoving = false; - gesture("start"); +function poke$1(q) { + if (!q._start) { + try { start$1(q); } // let the current task complete + catch (e) { + if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously + else if (!q._data) throw e; // await callback errored synchronously + } } +} - function mousemoved() { - noevent(); - mousemoving = true; - gestures.mouse("drag"); +function start$1(q) { + while (q._start = q._waiting && q._active < q._size) { + var i = q._ended + q._active, + t = q._tasks[i], + j = t.length - 1, + c = t[j]; + t[j] = end(q, i); + --q._waiting, ++q._active; + t = c.apply(null, t); + if (!q._tasks[i]) continue; // task finished synchronously + q._tasks[i] = t || noabort; } +} - function mouseupped() { - select(exports.event.view).on("mousemove.drag mouseup.drag", null); - yesdrag(exports.event.view, mousemoving); - noevent(); - gestures.mouse("end"); - } +function end(q, i) { + return function(e, r) { + if (!q._tasks[i]) return; // ignore multiple callbacks + --q._active, ++q._ended; + q._tasks[i] = null; + if (q._error != null) return; // ignore secondary errors + if (e != null) { + abort(q, e); + } else { + q._data[i] = r; + if (q._waiting) poke$1(q); + else maybeNotify(q); + } + }; +} - function touchstarted() { - if (!filter.apply(this, arguments)) return; - var touches$$1 = exports.event.changedTouches, - c = container.apply(this, arguments), - n = touches$$1.length, i, gesture; +function abort(q, e) { + var i = q._tasks.length, t; + q._error = e; // ignore active callbacks + q._data = undefined; // allow gc + q._waiting = NaN; // prevent starting - for (i = 0; i < n; ++i) { - if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) { - nopropagation(); - gesture("start"); + while (--i >= 0) { + if (t = q._tasks[i]) { + q._tasks[i] = null; + if (t.abort) { + try { t.abort(); } + catch (e) { /* ignore */ } } } } - function touchmoved() { - var touches$$1 = exports.event.changedTouches, - n = touches$$1.length, i, gesture; + q._active = NaN; // allow notification + maybeNotify(q); +} - for (i = 0; i < n; ++i) { - if (gesture = gestures[touches$$1[i].identifier]) { - noevent(); - gesture("drag"); - } - } +function maybeNotify(q) { + if (!q._active && q._call) { + var d = q._data; + q._data = undefined; // allow gc + q._call(q._error, d); } +} - function touchended() { - var touches$$1 = exports.event.changedTouches, - n = touches$$1.length, i, gesture; +function queue(concurrency) { + return new Queue(arguments.length ? +concurrency : Infinity); +} - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! - for (i = 0; i < n; ++i) { - if (gesture = gestures[touches$$1[i].identifier]) { - nopropagation(); - gesture("end"); - } - } - } +var uniform = function(min, max) { + min = min == null ? 0 : +min; + max = max == null ? 1 : +max; + if (arguments.length === 1) max = min, min = 0; + else max -= min; + return function() { + return Math.random() * max + min; + }; +}; - function beforestart(id, container, point, that, args) { - var p = point(container, id), s, dx, dy, - sublisteners = listeners.copy(); +var normal = function(mu, sigma) { + var x, r; + mu = mu == null ? 0 : +mu; + sigma = sigma == null ? 1 : +sigma; + return function() { + var y; - if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { - if ((exports.event.subject = s = subject.apply(that, args)) == null) return false; - dx = s.x - p[0] || 0; - dy = s.y - p[1] || 0; - return true; - })) return; + // If available, use the second previously-generated uniform random. + if (x != null) y = x, x = null; - return function gesture(type) { - var p0 = p, n; - switch (type) { - case "start": gestures[id] = gesture, n = active++; break; - case "end": delete gestures[id], --active; // nobreak - case "drag": p = point(container, id), n = active; break; - } - customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); - }; - } + // Otherwise, generate a new x and y. + else do { + x = Math.random() * 2 - 1; + y = Math.random() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); - drag.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$8(!!_), drag) : filter; + return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); }; +}; - drag.container = function(_) { - return arguments.length ? (container = typeof _ === "function" ? _ : constant$8(_), drag) : container; +var logNormal = function() { + var randomNormal = normal.apply(this, arguments); + return function() { + return Math.exp(randomNormal()); }; +}; - drag.subject = function(_) { - return arguments.length ? (subject = typeof _ === "function" ? _ : constant$8(_), drag) : subject; +var irwinHall = function(n) { + return function() { + for (var sum = 0, i = 0; i < n; ++i) sum += Math.random(); + return sum; }; +}; - drag.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? drag : value; +var bates = function(n) { + var randomIrwinHall = irwinHall(n); + return function() { + return randomIrwinHall() / n; }; - - return drag; }; -var constant$9 = function(x) { +var exponential$1 = function(lambda) { return function() { - return x; + return -Math.log(1 - Math.random()) / lambda; }; }; -function x$4(d) { - return d[0]; -} - -function y$4(d) { - return d[1]; -} - -function RedBlackTree() { - this._ = null; // root node -} - -function RedBlackNode(node) { - node.U = // parent node - node.C = // color - true for red, false for black - node.L = // left node - node.R = // right node - node.P = // previous node - node.N = null; // next node -} +var request = function(url, callback) { + var request, + event = dispatch("beforesend", "progress", "load", "error"), + mimeType, + headers = map$1(), + xhr = new XMLHttpRequest, + user = null, + password = null, + response, + responseType, + timeout = 0; -RedBlackTree.prototype = { - constructor: RedBlackTree, + // If IE does not support CORS, use XDomainRequest. + if (typeof XDomainRequest !== "undefined" + && !("withCredentials" in xhr) + && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; - insert: function(after, node) { - var parent, grandpa, uncle; + "onload" in xhr + ? xhr.onload = xhr.onerror = xhr.ontimeout = respond + : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; - 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; + function respond(o) { + var status = xhr.status, result; + if (!status && hasResponse(xhr) + || status >= 200 && status < 300 + || status === 304) { + if (response) { + try { + result = response.call(request, xhr); + } catch (e) { + event.call("error", request, e); + return; + } } else { - after.R = node; + result = xhr; } - parent = after; - } else if (this._) { - after = RedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; + event.call("load", request, result); } else { - node.P = node.N = null; - this._ = node; - parent = null; + event.call("error", request, o); } - 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) { - RedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - RedBlackRotateRight(this, grandpa); - } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - RedBlackRotateRight(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - RedBlackRotateLeft(this, grandpa); - } - } - parent = after.U; - } - this._.C = false; - }, + xhr.onprogress = function(e) { + event.call("progress", request, e); + }; - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; + request = { + header: function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers.get(name); + if (value == null) headers.remove(name); + else headers.set(name, value + ""); + return request; + }, - var parent = node.U, - sibling, - left = node.L, - right = node.R, - next, - red; + // If mimeType is non-null and no Accept header is set, a default is used. + mimeType: function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return request; + }, - if (!left) next = right; - else if (!right) next = left; - else next = RedBlackFirst(right); + // Specifies what type the response value should take; + // for instance, arraybuffer, blob, document, or text. + responseType: function(value) { + if (!arguments.length) return responseType; + responseType = value; + return request; + }, - if (parent) { - if (parent.L === node) parent.L = next; - else parent.R = next; - } else { - this._ = next; - } + timeout: function(value) { + if (!arguments.length) return timeout; + timeout = +value; + return request; + }, - 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 { - next.U = parent; - parent = next; - node = next.R; - } - } else { - red = node.C; - node = next; - } + user: function(value) { + return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); + }, - if (node) node.U = parent; - if (red) return; - if (node && node.C) { node.C = false; return; } + password: function(value) { + return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); + }, - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - RedBlackRotateLeft(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; - RedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - RedBlackRotateLeft(this, parent); - node = this._; - break; - } - } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - RedBlackRotateRight(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; - RedBlackRotateLeft(this, sibling); - sibling = parent.L; - } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - RedBlackRotateRight(this, parent); - node = this._; - break; - } - } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); + // Specify how to convert the response content to a specific type; + // changes the callback value on "load" events. + response: function(value) { + response = value; + return request; + }, - if (node) node.C = false; - } -}; + // Alias for send("GET", …). + get: function(data, callback) { + return request.send("GET", data, callback); + }, -function RedBlackRotateLeft(tree, node) { - var p = node, - q = node.R, - parent = p.U; + // Alias for send("POST", …). + post: function(data, callback) { + return request.send("POST", data, callback); + }, - if (parent) { - if (parent.L === p) parent.L = q; - else parent.R = q; - } else { - tree._ = q; - } + // If callback is non-null, it will be used for error and load events. + send: function(method, data, callback) { + xhr.open(method, url, true, user, password); + if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); + if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); + if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); + if (responseType != null) xhr.responseType = responseType; + if (timeout > 0) xhr.timeout = timeout; + if (callback == null && typeof data === "function") callback = data, data = null; + if (callback != null && callback.length === 1) callback = fixCallback(callback); + if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); + event.call("beforesend", request, xhr); + xhr.send(data == null ? null : data); + return request; + }, - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; -} + abort: function() { + xhr.abort(); + return request; + }, -function RedBlackRotateRight(tree, node) { - var p = node, - q = node.L, - parent = p.U; + on: function() { + var value = event.on.apply(event, arguments); + return value === event ? request : value; + } + }; - if (parent) { - if (parent.L === p) parent.L = q; - else parent.R = q; - } else { - tree._ = q; + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return request.get(callback); } - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; -} - -function RedBlackFirst(node) { - while (node.L) node = node.L; - return node; -} - -function createEdge(left, right, v0, v1) { - var edge = [null, null], - index = edges.push(edge) - 1; - edge.left = left; - edge.right = right; - if (v0) setEdgeEnd(edge, left, right, v0); - if (v1) setEdgeEnd(edge, right, left, v1); - cells[left.index].halfedges.push(index); - cells[right.index].halfedges.push(index); - return edge; -} + return request; +}; -function createBorderEdge(left, v0, v1) { - var edge = [v0, v1]; - edge.left = left; - return edge; +function fixCallback(callback) { + return function(error, xhr) { + callback(error == null ? xhr : null); + }; } -function setEdgeEnd(edge, left, right, vertex) { - if (!edge[0] && !edge[1]) { - edge[0] = vertex; - edge.left = left; - edge.right = right; - } else if (edge.left === right) { - edge[1] = vertex; - } else { - edge[0] = vertex; - } +function hasResponse(xhr) { + var type = xhr.responseType; + return type && type !== "text" + ? xhr.response // null on error + : xhr.responseText; // "" on error } -// Liang–Barsky line clipping. -function clipEdge(edge, x0, y0, x1, y1) { - var a = edge[0], - b = edge[1], - ax = a[0], - ay = a[1], - bx = b[0], - by = b[1], - t0 = 0, - t1 = 1, - dx = bx - ax, - dy = by - ay, - r; +var type$1 = function(defaultMimeType, response) { + return function(url, callback) { + var r = request(url).mimeType(defaultMimeType).response(response); + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return r.get(callback); + } + return 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; - } +var html = type$1("text/html", function(xhr) { + return document.createRange().createContextualFragment(xhr.responseText); +}); - 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; - } +var json = type$1("application/json", function(xhr) { + return JSON.parse(xhr.responseText); +}); - 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; - } +var text = type$1("text/plain", function(xhr) { + return xhr.responseText; +}); - 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; - } +var xml = type$1("application/xml", function(xhr) { + var xml = xhr.responseXML; + if (!xml) throw new Error("parse error"); + return xml; +}); - if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check? +var dsv$1 = function(defaultMimeType, parse) { + return function(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var r = request(url).mimeType(defaultMimeType); + r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; + r.row(row); + return callback ? r.get(callback) : r; + }; +}; - if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy]; - if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy]; - return true; +function responseOf(parse, row) { + return function(request$$1) { + return parse(request$$1.responseText, row); + }; } -function connectEdge(edge, x0, y0, x1, y1) { - var v1 = edge[1]; - if (v1) return true; +var csv$1 = dsv$1("text/csv", csvParse); - var v0 = edge[0], - left = edge.left, - right = edge.right, - lx = left[0], - ly = left[1], - rx = right[0], - ry = right[1], - fx = (lx + rx) / 2, - fy = (ly + ry) / 2, - fm, - fb; +var tsv$1 = dsv$1("text/tab-separated-values", tsvParse); - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!v0) v0 = [fx, y0]; - else if (v0[1] >= y1) return; - v1 = [fx, y1]; - } else { - if (!v0) v0 = [fx, y1]; - else if (v0[1] < y0) return; - v1 = [fx, y0]; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!v0) v0 = [(y0 - fb) / fm, y0]; - else if (v0[1] >= y1) return; - v1 = [(y1 - fb) / fm, y1]; - } else { - if (!v0) v0 = [(y1 - fb) / fm, y1]; - else if (v0[1] < y0) return; - v1 = [(y0 - fb) / fm, y0]; - } - } else { - if (ly < ry) { - if (!v0) v0 = [x0, fm * x0 + fb]; - else if (v0[0] >= x1) return; - v1 = [x1, fm * x1 + fb]; - } else { - if (!v0) v0 = [x1, fm * x1 + fb]; - else if (v0[0] < x0) return; - v1 = [x0, fm * x0 + fb]; - } - } - } +var array$2 = Array.prototype; + +var map$3 = array$2.map; +var slice$4 = array$2.slice; - edge[0] = v0; - edge[1] = v1; - return true; -} +var implicit = {name: "implicit"}; -function clipEdges(x0, y0, x1, y1) { - var i = edges.length, - edge; +function ordinal(range) { + var index = map$1(), + domain = [], + unknown = implicit; - while (i--) { - if (!connectEdge(edge = edges[i], x0, y0, x1, y1) - || !clipEdge(edge, x0, y0, x1, y1) - || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$3 - || Math.abs(edge[0][1] - edge[1][1]) > epsilon$3)) { - delete edges[i]; + range = range == null ? [] : slice$4.call(range); + + function scale(d) { + var key = d + "", i = index.get(key); + if (!i) { + if (unknown !== implicit) return unknown; + index.set(key, i = domain.push(d)); } + return range[(i - 1) % range.length]; } -} -function createCell(site) { - return cells[site.index] = { - site: site, - halfedges: [] + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = [], index = map$1(); + var i = -1, n = _.length, d, key; + while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); + return scale; }; -} -function cellHalfedgeAngle(cell, edge) { - var site = cell.site, - va = edge.left, - vb = edge.right; - if (site === vb) vb = va, va = site; - if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]); - if (site === va) va = edge[1], vb = edge[0]; - else va = edge[0], vb = edge[1]; - return Math.atan2(va[0] - vb[0], vb[1] - va[1]); -} + scale.range = function(_) { + return arguments.length ? (range = slice$4.call(_), scale) : range.slice(); + }; -function cellHalfedgeStart(cell, edge) { - return edge[+(edge.left !== cell.site)]; -} + scale.unknown = function(_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; -function cellHalfedgeEnd(cell, edge) { - return edge[+(edge.left === cell.site)]; -} + scale.copy = function() { + return ordinal() + .domain(domain) + .range(range) + .unknown(unknown); + }; -function sortCellHalfedges() { - for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { - if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { - var index = new Array(m), - array = new Array(m); - for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]); - index.sort(function(i, j) { return array[j] - array[i]; }); - for (j = 0; j < m; ++j) array[j] = halfedges[index[j]]; - for (j = 0; j < m; ++j) halfedges[j] = array[j]; - } - } + return scale; } -function clipCells(x0, y0, x1, y1) { - var nCells = cells.length, - iCell, - cell, - site, - iHalfedge, - halfedges, - nHalfedges, - start, - startX, - startY, - end, - endX, - endY, - cover = true; +function band() { + var scale = ordinal().unknown(undefined), + domain = scale.domain, + ordinalRange = scale.range, + range$$1 = [0, 1], + step, + bandwidth, + round = false, + paddingInner = 0, + paddingOuter = 0, + align = 0.5; - for (iCell = 0; iCell < nCells; ++iCell) { - if (cell = cells[iCell]) { - site = cell.site; - halfedges = cell.halfedges; - iHalfedge = halfedges.length; + delete scale.unknown; - // Remove any dangling clipped edges. - while (iHalfedge--) { - if (!edges[halfedges[iHalfedge]]) { - halfedges.splice(iHalfedge, 1); - } - } + function rescale() { + var n = domain().length, + reverse = range$$1[1] < range$$1[0], + start = range$$1[reverse - 0], + stop = range$$1[1 - reverse]; + step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); + if (round) step = Math.floor(step); + start += (stop - start - step * (n - paddingInner)) * align; + bandwidth = step * (1 - paddingInner); + if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); + var values = sequence(n).map(function(i) { return start + step * i; }); + return ordinalRange(reverse ? values.reverse() : values); + } - // Insert any border edges as necessary. - iHalfedge = 0, nHalfedges = halfedges.length; - while (iHalfedge < nHalfedges) { - end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1]; - start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; - if (Math.abs(endX - startX) > epsilon$3 || Math.abs(endY - startY) > epsilon$3) { - halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, - Math.abs(endX - x0) < epsilon$3 && y1 - endY > epsilon$3 ? [x0, Math.abs(startX - x0) < epsilon$3 ? startY : y1] - : Math.abs(endY - y1) < epsilon$3 && x1 - endX > epsilon$3 ? [Math.abs(startY - y1) < epsilon$3 ? startX : x1, y1] - : Math.abs(endX - x1) < epsilon$3 && endY - y0 > epsilon$3 ? [x1, Math.abs(startX - x1) < epsilon$3 ? startY : y0] - : Math.abs(endY - y0) < epsilon$3 && endX - x0 > epsilon$3 ? [Math.abs(startY - y0) < epsilon$3 ? startX : x0, y0] - : null)) - 1); - ++nHalfedges; - } - } + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; - if (nHalfedges) cover = false; - } - } + scale.range = function(_) { + return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice(); + }; - // If there weren’t any edges, have the closest site cover the extent. - // It doesn’t matter which corner of the extent we measure! - if (cover) { - var dx, dy, d2, dc = Infinity; + scale.rangeRound = function(_) { + return range$$1 = [+_[0], +_[1]], round = true, rescale(); + }; - for (iCell = 0, cover = null; iCell < nCells; ++iCell) { - if (cell = cells[iCell]) { - site = cell.site; - dx = site[0] - x0; - dy = site[1] - y0; - d2 = dx * dx + dy * dy; - if (d2 < dc) dc = d2, cover = cell; - } - } + scale.bandwidth = function() { + return bandwidth; + }; - if (cover) { - var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; - cover.halfedges.push( - edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, - edges.push(createBorderEdge(site, v01, v11)) - 1, - edges.push(createBorderEdge(site, v11, v10)) - 1, - edges.push(createBorderEdge(site, v10, v00)) - 1 - ); - } - } + scale.step = function() { + return step; + }; - // Lastly delete any cells with no edges; these were entirely clipped. - for (iCell = 0; iCell < nCells; ++iCell) { - if (cell = cells[iCell]) { - if (!cell.halfedges.length) { - delete cells[iCell]; - } - } - } -} + scale.round = function(_) { + return arguments.length ? (round = !!_, rescale()) : round; + }; -var circlePool = []; + scale.padding = function(_) { + return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; -var firstCircle; + scale.paddingInner = function(_) { + return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; -function Circle() { - RedBlackNode(this); - this.x = - this.y = - this.arc = - this.site = - this.cy = null; -} + scale.paddingOuter = function(_) { + return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter; + }; -function attachCircle(arc) { - var lArc = arc.P, - rArc = arc.N; + scale.align = function(_) { + return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; + }; - if (!lArc || !rArc) return; + scale.copy = function() { + return band() + .domain(domain()) + .range(range$$1) + .round(round) + .paddingInner(paddingInner) + .paddingOuter(paddingOuter) + .align(align); + }; - var lSite = lArc.site, - cSite = arc.site, - rSite = rArc.site; + return rescale(); +} - if (lSite === rSite) return; +function pointish(scale) { + var copy = scale.copy; - var bx = cSite[0], - by = cSite[1], - ax = lSite[0] - bx, - ay = lSite[1] - by, - cx = rSite[0] - bx, - cy = rSite[1] - by; + scale.padding = scale.paddingOuter; + delete scale.paddingInner; + delete scale.paddingOuter; - var d = 2 * (ax * cy - ay * cx); - if (d >= -epsilon2$1) return; + scale.copy = function() { + return pointish(copy()); + }; - var ha = ax * ax + ay * ay, - hc = cx * cx + cy * cy, - x = (cy * ha - ay * hc) / d, - y = (ax * hc - cx * ha) / d; + return scale; +} - var circle = circlePool.pop() || new Circle; - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom +function point$1() { + return pointish(band().paddingInner(1)); +} - arc.circle = circle; +var constant$9 = function(x) { + return function() { + return x; + }; +}; - var before = null, - node = circles._; +var number$1 = function(x) { + return +x; +}; - 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; } - } - } +var unit = [0, 1]; - circles.insert(before, circle); - if (!before) firstCircle = circle; +function deinterpolateLinear(a, b) { + return (b -= (a = +a)) + ? function(x) { return (x - a) / b; } + : constant$9(b); } -function detachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) firstCircle = circle.N; - circles.remove(circle); - circlePool.push(circle); - RedBlackNode(circle); - arc.circle = null; - } +function deinterpolateClamp(deinterpolate) { + return function(a, b) { + var d = deinterpolate(a = +a, b = +b); + return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; + }; } -var beachPool = []; +function reinterpolateClamp(reinterpolate) { + return function(a, b) { + var r = reinterpolate(a = +a, b = +b); + return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; + }; +} -function Beach() { - RedBlackNode(this); - this.edge = - this.site = - this.circle = null; +function bimap(domain, range$$1, deinterpolate, reinterpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1]; + if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); + else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); + return function(x) { return r0(d0(x)); }; } -function createBeach(site) { - var beach = beachPool.pop() || new Beach; - beach.site = site; - return beach; +function polymap(domain, range$$1, deinterpolate, reinterpolate) { + var j = Math.min(domain.length, range$$1.length) - 1, + d = new Array(j), + r = new Array(j), + i = -1; + + // Reverse descending domains. + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range$$1 = range$$1.slice().reverse(); + } + + while (++i < j) { + d[i] = deinterpolate(domain[i], domain[i + 1]); + r[i] = reinterpolate(range$$1[i], range$$1[i + 1]); + } + + return function(x) { + var i = bisectRight(domain, x, 1, j) - 1; + return r[i](d[i](x)); + }; } -function detachBeach(beach) { - detachCircle(beach); - beaches.remove(beach); - beachPool.push(beach); - RedBlackNode(beach); +function copy(source, target) { + return target + .domain(source.domain()) + .range(source.range()) + .interpolate(source.interpolate()) + .clamp(source.clamp()); } -function removeBeach(beach) { - var circle = beach.circle, - x = circle.x, - y = circle.cy, - vertex = [x, y], - previous = beach.P, - next = beach.N, - disappearing = [beach]; +// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. +// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. +function continuous(deinterpolate, reinterpolate) { + var domain = unit, + range$$1 = unit, + interpolate$$1 = interpolateValue, + clamp = false, + piecewise, + output, + input; - detachBeach(beach); + function rescale() { + piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap; + output = input = null; + return scale; + } - var lArc = previous; - while (lArc.circle - && Math.abs(x - lArc.circle.x) < epsilon$3 - && Math.abs(y - lArc.circle.cy) < epsilon$3) { - previous = lArc.P; - disappearing.unshift(lArc); - detachBeach(lArc); - lArc = previous; + function scale(x) { + return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); } - disappearing.unshift(lArc); - detachCircle(lArc); + scale.invert = function(y) { + return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); + }; - var rArc = next; - while (rArc.circle - && Math.abs(x - rArc.circle.x) < epsilon$3 - && Math.abs(y - rArc.circle.cy) < epsilon$3) { - next = rArc.N; - disappearing.push(rArc); - detachBeach(rArc); - rArc = next; - } + scale.domain = function(_) { + return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice(); + }; - disappearing.push(rArc); - detachCircle(rArc); + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice(); + }; - var nArcs = disappearing.length, - iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); - } + scale.rangeRound = function(_) { + return range$$1 = slice$4.call(_), interpolate$$1 = interpolateRound, rescale(); + }; - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = createEdge(lArc.site, rArc.site, null, vertex); + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, rescale()) : clamp; + }; - attachCircle(lArc); - attachCircle(rArc); -} + scale.interpolate = function(_) { + return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; + }; -function addBeach(site) { - var x = site[0], - directrix = site[1], - lArc, - rArc, - dxl, - dxr, - node = beaches._; + return rescale(); +} - while (node) { - dxl = leftBreakPoint(node, directrix) - x; - if (dxl > epsilon$3) node = node.L; else { - dxr = x - rightBreakPoint(node, directrix); - if (dxr > epsilon$3) { - if (!node.R) { - lArc = node; - break; - } - node = node.R; - } else { - if (dxl > -epsilon$3) { - lArc = node.P; - rArc = node; - } else if (dxr > -epsilon$3) { - lArc = node; - rArc = node.N; - } else { - lArc = rArc = node; - } - break; - } +var tickFormat = function(domain, count, specifier) { + var start = domain[0], + stop = domain[domain.length - 1], + step = tickStep(start, stop, count == null ? 10 : count), + precision; + specifier = formatSpecifier(specifier == null ? ",f" : specifier); + switch (specifier.type) { + case "s": { + var value = Math.max(Math.abs(start), Math.abs(stop)); + if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision; + return exports.formatPrefix(specifier, value); + } + case "": + case "e": + case "g": + case "p": + case "r": { + if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); + break; + } + case "f": + case "%": { + if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; + break; } } + return exports.format(specifier); +}; - createCell(site); - var newArc = createBeach(site); - beaches.insert(lArc, newArc); +function linearish(scale) { + var domain = scale.domain; - if (!lArc && !rArc) return; + scale.ticks = function(count) { + var d = domain(); + return ticks(d[0], d[d.length - 1], count == null ? 10 : count); + }; - if (lArc === rArc) { - detachCircle(lArc); - rArc = createBeach(lArc.site); - beaches.insert(newArc, rArc); - newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site); - attachCircle(lArc); - attachCircle(rArc); - return; - } + scale.tickFormat = function(count, specifier) { + return tickFormat(domain(), count, specifier); + }; + + scale.nice = function(count) { + var d = domain(), + i = d.length - 1, + n = count == null ? 10 : count, + start = d[0], + stop = d[i], + step = tickStep(start, stop, n); + + if (step) { + step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n); + d[0] = Math.floor(start / step) * step; + d[i] = Math.ceil(stop / step) * step; + domain(d); + } - if (!rArc) { // && lArc - newArc.edge = createEdge(lArc.site, newArc.site); - return; - } + return scale; + }; - // else lArc !== rArc - detachCircle(lArc); - detachCircle(rArc); + return scale; +} - var lSite = lArc.site, - ax = lSite[0], - ay = lSite[1], - bx = site[0] - ax, - by = site[1] - ay, - rSite = rArc.site, - cx = rSite[0] - ax, - cy = rSite[1] - ay, - d = 2 * (bx * cy - by * cx), - hb = bx * bx + by * by, - hc = cx * cx + cy * cy, - vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay]; +function linear$2() { + var scale = continuous(deinterpolateLinear, reinterpolate); - setEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = createEdge(lSite, site, null, vertex); - rArc.edge = createEdge(site, rSite, null, vertex); - attachCircle(lArc); - attachCircle(rArc); + scale.copy = function() { + return copy(scale, linear$2()); + }; + + return linearish(scale); } -function leftBreakPoint(arc, directrix) { - var site = arc.site, - rfocx = site[0], - rfocy = site[1], - pby2 = rfocy - directrix; +function identity$6() { + var domain = [0, 1]; - if (!pby2) return rfocx; + function scale(x) { + return +x; + } - var lArc = arc.P; - if (!lArc) return -Infinity; + scale.invert = scale; - site = lArc.site; - var lfocx = site[0], - lfocy = site[1], - plby2 = lfocy - directrix; + scale.domain = scale.range = function(_) { + return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice(); + }; - if (!plby2) return lfocx; + scale.copy = function() { + return identity$6().domain(domain); + }; - var hl = lfocx - rfocx, - aby2 = 1 / pby2 - 1 / plby2, - b = hl / plby2; + return linearish(scale); +} - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; +var nice = function(domain, interval) { + domain = domain.slice(); - return (rfocx + lfocx) / 2; -} + var i0 = 0, + i1 = domain.length - 1, + x0 = domain[i0], + x1 = domain[i1], + t; -function rightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return leftBreakPoint(rArc, directrix); - var site = arc.site; - return site[1] === directrix ? site[0] : Infinity; -} + if (x1 < x0) { + t = i0, i0 = i1, i1 = t; + t = x0, x0 = x1, x1 = t; + } -var epsilon$3 = 1e-6; -var epsilon2$1 = 1e-12; -var beaches; -var cells; -var circles; -var edges; + domain[i0] = interval.floor(x0); + domain[i1] = interval.ceil(x1); + return domain; +}; -function triangleArea(a, b, c) { - return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); +function deinterpolate(a, b) { + return (b = Math.log(b / a)) + ? function(x) { return Math.log(x / a) / b; } + : constant$9(b); } -function lexicographic(a, b) { - return b[1] - a[1] - || b[0] - a[0]; +function reinterpolate$1(a, b) { + return a < 0 + ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); } + : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); }; } -function Diagram(sites, extent) { - var site = sites.sort(lexicographic).pop(), - x, - y, - circle; - - edges = []; - cells = new Array(sites.length); - beaches = new RedBlackTree; - circles = new RedBlackTree; +function pow10(x) { + return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; +} - while (true) { - circle = firstCircle; - if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { - if (site[0] !== x || site[1] !== y) { - addBeach(site); - x = site[0], y = site[1]; - } - site = sites.pop(); - } else if (circle) { - removeBeach(circle.arc); - } else { - break; - } - } +function powp(base) { + return base === 10 ? pow10 + : base === Math.E ? Math.exp + : function(x) { return Math.pow(base, x); }; +} - sortCellHalfedges(); +function logp(base) { + return base === Math.E ? Math.log + : base === 10 && Math.log10 + || base === 2 && Math.log2 + || (base = Math.log(base), function(x) { return Math.log(x) / base; }); +} - if (extent) { - var x0 = +extent[0][0], - y0 = +extent[0][1], - x1 = +extent[1][0], - y1 = +extent[1][1]; - clipEdges(x0, y0, x1, y1); - clipCells(x0, y0, x1, y1); - } +function reflect(f) { + return function(x) { + return -f(-x); + }; +} - this.edges = edges; - this.cells = cells; +function log$1() { + var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]), + domain = scale.domain, + base = 10, + logs = logp(10), + pows = powp(10); - beaches = - circles = - edges = - cells = null; -} + function rescale() { + logs = logp(base), pows = powp(base); + if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows); + return scale; + } -Diagram.prototype = { - constructor: Diagram, + scale.base = function(_) { + return arguments.length ? (base = +_, rescale()) : base; + }; - polygons: function() { - var edges = this.edges; + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; - return this.cells.map(function(cell) { - var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); }); - polygon.data = cell.site.data; - return polygon; - }); - }, + scale.ticks = function(count) { + var d = domain(), + u = d[0], + v = d[d.length - 1], + r; - triangles: function() { - var triangles = [], - edges = this.edges; + if (r = v < u) i = u, u = v, v = i; - this.cells.forEach(function(cell, i) { - var site = cell.site, - halfedges = cell.halfedges, - j = -1, - m = halfedges.length, - s0, - e1 = edges[halfedges[m - 1]], - s1 = e1.left === site ? e1.right : e1.left; + var i = logs(u), + j = logs(v), + p, + k, + t, + n = count == null ? 10 : +count, + z = []; - while (++j < m) { - s0 = s1; - e1 = edges[halfedges[j]]; - s1 = e1.left === site ? e1.right : e1.left; - if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { - triangles.push([site.data, s0.data, s1.data]); + if (!(base % 1) && j - i < n) { + i = Math.round(i) - 1, j = Math.round(j) + 1; + if (u > 0) for (; i < j; ++i) { + for (k = 1, p = pows(i); k < base; ++k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); + } + } else for (; i < j; ++i) { + for (k = base - 1, p = pows(i); k >= 1; --k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); } } - }); + } else { + z = ticks(i, j, Math.min(j - i, n)).map(pows); + } - return triangles; - }, + return r ? z.reverse() : z; + }; + + scale.tickFormat = function(count, specifier) { + if (specifier == null) specifier = base === 10 ? ".0e" : ","; + if (typeof specifier !== "function") specifier = exports.format(specifier); + if (count === Infinity) return specifier; + if (count == null) count = 10; + var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? + return function(d) { + var i = d / pows(Math.round(logs(d))); + if (i * base < base - 0.5) i *= base; + return i <= k ? specifier(d) : ""; + }; + }; + + scale.nice = function() { + return domain(nice(domain(), { + floor: function(x) { return pows(Math.floor(logs(x))); }, + ceil: function(x) { return pows(Math.ceil(logs(x))); } + })); + }; - links: function() { - return this.edges.filter(function(edge) { - return edge.right; - }).map(function(edge) { - return { - source: edge.left.data, - target: edge.right.data - }; - }); - }, + scale.copy = function() { + return copy(scale, log$1().base(base)); + }; - find: function(x, y, radius) { - var that = this, - i0, i1 = that._found || 0, - cell = that.cells[i1] || that.cells[i1 = 0], - dx = x - cell.site[0], - dy = y - cell.site[1], - d2 = dx * dx + dy * dy; + return scale; +} - do { - cell = that.cells[i0 = i1], i1 = null; - cell.halfedges.forEach(function(e) { - var edge = that.edges[e], v = edge.left; - if ((v === cell.site || !v) && !(v = edge.right)) return; - var vx = x - v[0], - vy = y - v[1], - v2 = vx * vx + vy * vy; - if (v2 < d2) d2 = v2, i1 = v.index; - }); - } while (i1 !== null); +function raise$1(x, exponent) { + return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); +} - that._found = i0; +function pow$1() { + var exponent = 1, + scale = continuous(deinterpolate, reinterpolate), + domain = scale.domain; - return radius == null || d2 <= radius * radius ? cell.site : null; + function deinterpolate(a, b) { + return (b = raise$1(b, exponent) - (a = raise$1(a, exponent))) + ? function(x) { return (raise$1(x, exponent) - a) / b; } + : constant$9(b); } -}; - -var voronoi = function() { - var x$$1 = x$4, - y$$1 = y$4, - extent = null; - function voronoi(data) { - return new Diagram(data.map(function(d, i) { - var s = [Math.round(x$$1(d, i, data) / epsilon$3) * epsilon$3, Math.round(y$$1(d, i, data) / epsilon$3) * epsilon$3]; - s.index = i; - s.data = d; - return s; - }), extent); + function reinterpolate(a, b) { + b = raise$1(b, exponent) - (a = raise$1(a, exponent)); + return function(t) { return raise$1(a + b * t, 1 / exponent); }; } - voronoi.polygons = function(data) { - return voronoi(data).polygons(); + scale.exponent = function(_) { + return arguments.length ? (exponent = +_, domain(domain())) : exponent; }; - voronoi.links = function(data) { - return voronoi(data).links(); + scale.copy = function() { + return copy(scale, pow$1().exponent(exponent)); }; - voronoi.triangles = function(data) { - return voronoi(data).triangles(); - }; + return linearish(scale); +} - voronoi.x = function(_) { - return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : x$$1; - }; +function sqrt$1() { + return pow$1().exponent(0.5); +} - voronoi.y = function(_) { - return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : y$$1; +function quantile$$1() { + var domain = [], + range$$1 = [], + thresholds = []; + + function rescale() { + var i = 0, n = Math.max(1, range$$1.length); + thresholds = new Array(n - 1); + while (++i < n) thresholds[i - 1] = threshold(domain, i / n); + return scale; + } + + function scale(x) { + if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)]; + } + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] : [ + i > 0 ? thresholds[i - 1] : domain[0], + i < thresholds.length ? thresholds[i] : domain[domain.length - 1] + ]; }; - voronoi.extent = function(_) { - return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]]; + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = []; + for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d); + domain.sort(ascending); + return rescale(); }; - voronoi.size = function(_) { - return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]]; + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice(); }; - return voronoi; -}; + scale.quantiles = function() { + return thresholds.slice(); + }; -var constant$10 = function(x) { - return function() { - return x; + scale.copy = function() { + return quantile$$1() + .domain(domain) + .range(range$$1); }; -}; -function ZoomEvent(target, type, transform) { - this.target = target; - this.type = type; - this.transform = transform; + return scale; } -function Transform(k, x, y) { - this.k = k; - this.x = x; - this.y = y; -} +function quantize$1() { + var x0 = 0, + x1 = 1, + n = 1, + domain = [0.5], + range$$1 = [0, 1]; -Transform.prototype = { - constructor: Transform, - scale: function(k) { - return k === 1 ? this : new Transform(this.k * k, this.x, this.y); - }, - translate: function(x, y) { - return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); - }, - apply: function(point) { - return [point[0] * this.k + this.x, point[1] * this.k + this.y]; - }, - applyX: function(x) { - return x * this.k + this.x; - }, - applyY: function(y) { - return y * this.k + this.y; - }, - invert: function(location) { - return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; - }, - invertX: function(x) { - return (x - this.x) / this.k; - }, - invertY: function(y) { - return (y - this.y) / this.k; - }, - rescaleX: function(x) { - return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); - }, - rescaleY: function(y) { - return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); - }, - toString: function() { - return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + function scale(x) { + if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; } -}; -var identity$6 = new Transform(1, 0, 0); + function rescale() { + var i = -1; + domain = new Array(n); + while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); + return scale; + } -transform.prototype = Transform.prototype; + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; + }; -function transform(node) { - return node.__zoom || identity$6; -} + scale.range = function(_) { + return arguments.length ? (n = (range$$1 = slice$4.call(_)).length - 1, rescale()) : range$$1.slice(); + }; -function nopropagation$1() { - exports.event.stopImmediatePropagation(); -} + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] + : i < 1 ? [x0, domain[0]] + : i >= n ? [domain[n - 1], x1] + : [domain[i - 1], domain[i]]; + }; -var noevent$1 = function() { - exports.event.preventDefault(); - exports.event.stopImmediatePropagation(); -}; + scale.copy = function() { + return quantize$1() + .domain([x0, x1]) + .range(range$$1); + }; -// Ignore right-click, since that should open the context menu. -function defaultFilter$1() { - return !exports.event.button; + return linearish(scale); } -function defaultExtent() { - var e = this, w, h; - if (e instanceof SVGElement) { - e = e.ownerSVGElement || e; - w = e.width.baseVal.value; - h = e.height.baseVal.value; - } else { - w = e.clientWidth; - h = e.clientHeight; +function threshold$1() { + var domain = [0.5], + range$$1 = [0, 1], + n = 1; + + function scale(x) { + if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; } - return [[0, 0], [w, h]]; -} -function defaultTransform() { - return this.__zoom || identity$6; -} + scale.domain = function(_) { + return arguments.length ? (domain = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice(); + }; -var zoom = function() { - var filter = defaultFilter$1, - extent = defaultExtent, - k0 = 0, - k1 = Infinity, - x0 = -k1, - x1 = k1, - y0 = x0, - y1 = x1, - duration = 250, - gestures = [], - listeners = dispatch("start", "zoom", "end"), - touchstarting, - touchending, - touchDelay = 500, - wheelDelay = 150; + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice(); + }; - function zoom(selection$$1) { - selection$$1 - .on("wheel.zoom", wheeled) - .on("mousedown.zoom", mousedowned) - .on("dblclick.zoom", dblclicked) - .on("touchstart.zoom", touchstarted) - .on("touchmove.zoom", touchmoved) - .on("touchend.zoom touchcancel.zoom", touchended) - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") - .property("__zoom", defaultTransform); + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return [domain[i - 1], domain[i]]; + }; + + scale.copy = function() { + return threshold$1() + .domain(domain) + .range(range$$1); + }; + + return scale; +} + +var t0$1 = new Date; +var t1$1 = new Date; + +function newInterval(floori, offseti, count, field) { + + function interval(date) { + return floori(date = new Date(+date)), date; } - zoom.transform = function(collection, transform) { - var selection$$1 = collection.selection ? collection.selection() : collection; - selection$$1.property("__zoom", defaultTransform); - if (collection !== selection$$1) { - schedule(collection, transform); - } else { - selection$$1.interrupt().each(function() { - gesture(this, arguments) - .start() - .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform) - .end(); - }); - } + interval.floor = interval; + + interval.ceil = function(date) { + return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; }; - zoom.scaleBy = function(selection$$1, k) { - zoom.scaleTo(selection$$1, function() { - var k0 = this.__zoom.k, - k1 = typeof k === "function" ? k.apply(this, arguments) : k; - return k0 * k1; - }); + interval.round = function(date) { + var d0 = interval(date), + d1 = interval.ceil(date); + return date - d0 < d1 - date ? d0 : d1; }; - zoom.scaleTo = function(selection$$1, k) { - zoom.transform(selection$$1, function() { - var e = extent.apply(this, arguments), - t0 = this.__zoom, - p0 = centroid(e), - p1 = t0.invert(p0), - k1 = typeof k === "function" ? k.apply(this, arguments) : k; - return constrain(translate(scale(t0, k1), p0, p1), e); - }); + interval.offset = function(date, step) { + return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; }; - zoom.translateBy = function(selection$$1, x, y) { - zoom.transform(selection$$1, function() { - return constrain(this.__zoom.translate( - typeof x === "function" ? x.apply(this, arguments) : x, - typeof y === "function" ? y.apply(this, arguments) : y - ), extent.apply(this, arguments)); + interval.range = function(start, stop, step) { + var range = []; + start = interval.ceil(start); + step = step == null ? 1 : Math.floor(step); + if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date + do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) + return range; + }; + + interval.filter = function(test) { + return newInterval(function(date) { + if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); + }, function(date, step) { + if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty }); }; - function scale(transform, k) { - k = Math.max(k0, Math.min(k1, k)); - return k === transform.k ? transform : new Transform(k, transform.x, transform.y); - } + if (count) { + interval.count = function(start, end) { + t0$1.setTime(+start), t1$1.setTime(+end); + floori(t0$1), floori(t1$1); + return Math.floor(count(t0$1, t1$1)); + }; - function translate(transform, p0, p1) { - var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k; - return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y); + interval.every = function(step) { + step = Math.floor(step); + return !isFinite(step) || !(step > 0) ? null + : !(step > 1) ? interval + : interval.filter(field + ? function(d) { return field(d) % step === 0; } + : function(d) { return interval.count(0, d) % step === 0; }); + }; } - function constrain(transform, extent) { - var dx = Math.min(0, transform.invertX(extent[0][0]) - x0) || Math.max(0, transform.invertX(extent[1][0]) - x1), - dy = Math.min(0, transform.invertY(extent[0][1]) - y0) || Math.max(0, transform.invertY(extent[1][1]) - y1); - return dx || dy ? transform.translate(dx, dy) : transform; - } + return interval; +} - function centroid(extent) { - return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; - } +var millisecond = newInterval(function() { + // noop +}, function(date, step) { + date.setTime(+date + step); +}, function(start, end) { + return end - start; +}); - function schedule(transition$$1, transform, center) { - transition$$1 - .on("start.zoom", function() { gesture(this, arguments).start(); }) - .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); }) - .tween("zoom", function() { - var that = this, - args = arguments, - g = gesture(that, args), - e = extent.apply(that, args), - p = center || centroid(e), - w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), - a = that.__zoom, - b = typeof transform === "function" ? transform.apply(that, args) : transform, - i = interpolateZoom(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); - return function(t) { - if (t === 1) t = b; // Avoid rounding error on end. - else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } - g.zoom(null, t); - }; - }); - } +// An optimized implementation for this simple case. +millisecond.every = function(k) { + k = Math.floor(k); + if (!isFinite(k) || !(k > 0)) return null; + if (!(k > 1)) return millisecond; + return newInterval(function(date) { + date.setTime(Math.floor(date / k) * k); + }, function(date, step) { + date.setTime(+date + step * k); + }, function(start, end) { + return (end - start) / k; + }); +}; - function gesture(that, args) { - for (var i = 0, n = gestures.length, g; i < n; ++i) { - if ((g = gestures[i]).that === that) { - return g; - } - } - return new Gesture(that, args); - } +var milliseconds = millisecond.range; - function Gesture(that, args) { - this.that = that; - this.args = args; - this.index = -1; - this.active = 0; - this.extent = extent.apply(that, args); - } +var durationSecond$1 = 1e3; +var durationMinute$1 = 6e4; +var durationHour$1 = 36e5; +var durationDay$1 = 864e5; +var durationWeek$1 = 6048e5; - Gesture.prototype = { - start: function() { - if (++this.active === 1) { - this.index = gestures.push(this) - 1; - this.emit("start"); - } - return this; - }, - zoom: function(key, transform) { - if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]); - if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]); - if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]); - this.that.__zoom = transform; - this.emit("zoom"); - return this; - }, - end: function() { - if (--this.active === 0) { - gestures.splice(this.index, 1); - this.index = -1; - this.emit("end"); - } - return this; - }, - emit: function(type) { - customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); - } - }; +var second = newInterval(function(date) { + date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1); +}, function(date, step) { + date.setTime(+date + step * durationSecond$1); +}, function(start, end) { + return (end - start) / durationSecond$1; +}, function(date) { + return date.getUTCSeconds(); +}); - function wheeled() { - if (!filter.apply(this, arguments)) return; - var g = gesture(this, arguments), - t = this.__zoom, - k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -exports.event.deltaY * (exports.event.deltaMode ? 120 : 1) / 500))), - p = mouse(this); +var seconds = second.range; - // If the mouse is in the same location as before, reuse it. - // If there were recent wheel events, reset the wheel idle timeout. - if (g.wheel) { - if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { - g.mouse[1] = t.invert(g.mouse[0] = p); - } - clearTimeout(g.wheel); - } +var minute = newInterval(function(date) { + date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1); +}, function(date, step) { + date.setTime(+date + step * durationMinute$1); +}, function(start, end) { + return (end - start) / durationMinute$1; +}, function(date) { + return date.getMinutes(); +}); - // If this wheel event won’t trigger a transform change, ignore it. - else if (t.k === k) return; +var minutes = minute.range; - // Otherwise, capture the mouse point and location at the start. - else { - g.mouse = [p, t.invert(p)]; - interrupt(this); - g.start(); - } +var hour = newInterval(function(date) { + var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1; + if (offset < 0) offset += durationHour$1; + date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset); +}, function(date, step) { + date.setTime(+date + step * durationHour$1); +}, function(start, end) { + return (end - start) / durationHour$1; +}, function(date) { + return date.getHours(); +}); - noevent$1(); - g.wheel = setTimeout(wheelidled, wheelDelay); - g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent)); +var hours = hour.range; - function wheelidled() { - g.wheel = null; - g.end(); - } - } +var day = newInterval(function(date) { + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setDate(date.getDate() + step); +}, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1; +}, function(date) { + return date.getDate() - 1; +}); + +var days = day.range; + +function weekday(i) { + return newInterval(function(date) { + date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setDate(date.getDate() + step * 7); + }, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1; + }); +} + +var sunday = weekday(0); +var monday = weekday(1); +var tuesday = weekday(2); +var wednesday = weekday(3); +var thursday = weekday(4); +var friday = weekday(5); +var saturday = weekday(6); - function mousedowned() { - if (touchending || !filter.apply(this, arguments)) return; - var g = gesture(this, arguments), - v = select(exports.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), - p = mouse(this); +var sundays = sunday.range; +var mondays = monday.range; +var tuesdays = tuesday.range; +var wednesdays = wednesday.range; +var thursdays = thursday.range; +var fridays = friday.range; +var saturdays = saturday.range; - dragDisable(exports.event.view); - nopropagation$1(); - g.mouse = [p, this.__zoom.invert(p)]; - interrupt(this); - g.start(); +var month = newInterval(function(date) { + date.setDate(1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setMonth(date.getMonth() + step); +}, function(start, end) { + return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; +}, function(date) { + return date.getMonth(); +}); - function mousemoved() { - noevent$1(); - g.moved = true; - g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent)); - } +var months = month.range; - function mouseupped() { - v.on("mousemove.zoom mouseup.zoom", null); - yesdrag(exports.event.view, g.moved); - noevent$1(); - g.end(); - } - } +var year = newInterval(function(date) { + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setFullYear(date.getFullYear() + step); +}, function(start, end) { + return end.getFullYear() - start.getFullYear(); +}, function(date) { + return date.getFullYear(); +}); - function dblclicked() { - if (!filter.apply(this, arguments)) return; - var t0 = this.__zoom, - p0 = mouse(this), - p1 = t0.invert(p0), - k1 = t0.k * (exports.event.shiftKey ? 0.5 : 2), - t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments)); +// An optimized implementation for this simple case. +year.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setFullYear(Math.floor(date.getFullYear() / k) * k); + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setFullYear(date.getFullYear() + step * k); + }); +}; - noevent$1(); - if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0); - else select(this).call(zoom.transform, t1); - } +var years = year.range; - function touchstarted() { - if (!filter.apply(this, arguments)) return; - var g = gesture(this, arguments), - touches$$1 = exports.event.changedTouches, - n = touches$$1.length, i, t, p; +var utcMinute = newInterval(function(date) { + date.setUTCSeconds(0, 0); +}, function(date, step) { + date.setTime(+date + step * durationMinute$1); +}, function(start, end) { + return (end - start) / durationMinute$1; +}, function(date) { + return date.getUTCMinutes(); +}); - nopropagation$1(); - for (i = 0; i < n; ++i) { - t = touches$$1[i], p = touch(this, touches$$1, t.identifier); - p = [p, this.__zoom.invert(p), t.identifier]; - if (!g.touch0) g.touch0 = p; - else if (!g.touch1) g.touch1 = p; - } - if (touchstarting) { - touchstarting = clearTimeout(touchstarting); - if (!g.touch1) return g.end(), dblclicked.apply(this, arguments); - } - if (exports.event.touches.length === n) { - touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); - interrupt(this); - g.start(); - } - } +var utcMinutes = utcMinute.range; - function touchmoved() { - var g = gesture(this, arguments), - touches$$1 = exports.event.changedTouches, - n = touches$$1.length, i, t, p, l; +var utcHour = newInterval(function(date) { + date.setUTCMinutes(0, 0, 0); +}, function(date, step) { + date.setTime(+date + step * durationHour$1); +}, function(start, end) { + return (end - start) / durationHour$1; +}, function(date) { + return date.getUTCHours(); +}); - noevent$1(); - if (touchstarting) touchstarting = clearTimeout(touchstarting); - for (i = 0; i < n; ++i) { - t = touches$$1[i], p = touch(this, touches$$1, t.identifier); - if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; - else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; - } - t = g.that.__zoom; - if (g.touch1) { - var p0 = g.touch0[0], l0 = g.touch0[1], - p1 = g.touch1[0], l1 = g.touch1[1], - dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, - dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; - t = scale(t, Math.sqrt(dp / dl)); - p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; - l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; - } - else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; - else return; - g.zoom("touch", constrain(translate(t, p, l), g.extent)); - } +var utcHours = utcHour.range; - function touchended() { - var g = gesture(this, arguments), - touches$$1 = exports.event.changedTouches, - n = touches$$1.length, i, t; +var utcDay = newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCDate(date.getUTCDate() + step); +}, function(start, end) { + return (end - start) / durationDay$1; +}, function(date) { + return date.getUTCDate() - 1; +}); - nopropagation$1(); - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, touchDelay); - for (i = 0; i < n; ++i) { - t = touches$$1[i]; - if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; - else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; - } - if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; - if (!g.touch0) g.end(); - } +var utcDays = utcDay.range; - zoom.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$10(!!_), zoom) : filter; - }; +function utcWeekday(i) { + return newInterval(function(date) { + date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCDate(date.getUTCDate() + step * 7); + }, function(start, end) { + return (end - start) / durationWeek$1; + }); +} - zoom.extent = function(_) { - return arguments.length ? (extent = typeof _ === "function" ? _ : constant$10([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; - }; +var utcSunday = utcWeekday(0); +var utcMonday = utcWeekday(1); +var utcTuesday = utcWeekday(2); +var utcWednesday = utcWeekday(3); +var utcThursday = utcWeekday(4); +var utcFriday = utcWeekday(5); +var utcSaturday = utcWeekday(6); - zoom.scaleExtent = function(_) { - return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1]; - }; +var utcSundays = utcSunday.range; +var utcMondays = utcMonday.range; +var utcTuesdays = utcTuesday.range; +var utcWednesdays = utcWednesday.range; +var utcThursdays = utcThursday.range; +var utcFridays = utcFriday.range; +var utcSaturdays = utcSaturday.range; - zoom.translateExtent = function(_) { - return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]]; - }; +var utcMonth = newInterval(function(date) { + date.setUTCDate(1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCMonth(date.getUTCMonth() + step); +}, function(start, end) { + return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; +}, function(date) { + return date.getUTCMonth(); +}); - zoom.duration = function(_) { - return arguments.length ? (duration = +_, zoom) : duration; - }; +var utcMonths = utcMonth.range; - zoom.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? zoom : value; - }; +var utcYear = newInterval(function(date) { + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step); +}, function(start, end) { + return end.getUTCFullYear() - start.getUTCFullYear(); +}, function(date) { + return date.getUTCFullYear(); +}); - return zoom; +// An optimized implementation for this simple case. +utcYear.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step * k); + }); }; -var constant$11 = function(x) { - return function() { - return x; - }; -}; +var utcYears = utcYear.range; -var BrushEvent = function(target, type, selection) { - this.target = target; - this.type = type; - this.selection = selection; -}; +function localDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); + date.setFullYear(d.y); + return date; + } + return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); +} -function nopropagation$2() { - exports.event.stopImmediatePropagation(); +function utcDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); + date.setUTCFullYear(d.y); + return date; + } + return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); } -var noevent$2 = function() { - exports.event.preventDefault(); - exports.event.stopImmediatePropagation(); -}; - -var MODE_DRAG = {name: "drag"}; -var MODE_SPACE = {name: "space"}; -var MODE_HANDLE = {name: "handle"}; -var MODE_CENTER = {name: "center"}; +function newYear(y) { + return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; +} -var X = { - name: "x", - handles: ["e", "w"].map(type$1), - input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; }, - output: function(xy) { return xy && [xy[0][0], xy[1][0]]; } -}; +function formatLocale$1(locale) { + var locale_dateTime = locale.dateTime, + locale_date = locale.date, + locale_time = locale.time, + locale_periods = locale.periods, + locale_weekdays = locale.days, + locale_shortWeekdays = locale.shortDays, + locale_months = locale.months, + locale_shortMonths = locale.shortMonths; -var Y = { - name: "y", - handles: ["n", "s"].map(type$1), - input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; }, - output: function(xy) { return xy && [xy[0][1], xy[1][1]]; } -}; + var periodRe = formatRe(locale_periods), + periodLookup = formatLookup(locale_periods), + weekdayRe = formatRe(locale_weekdays), + weekdayLookup = formatLookup(locale_weekdays), + shortWeekdayRe = formatRe(locale_shortWeekdays), + shortWeekdayLookup = formatLookup(locale_shortWeekdays), + monthRe = formatRe(locale_months), + monthLookup = formatLookup(locale_months), + shortMonthRe = formatRe(locale_shortMonths), + shortMonthLookup = formatLookup(locale_shortMonths); -var XY = { - name: "xy", - handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$1), - input: function(xy) { return xy; }, - output: function(xy) { return xy; } -}; + var formats = { + "a": formatShortWeekday, + "A": formatWeekday, + "b": formatShortMonth, + "B": formatMonth, + "c": null, + "d": formatDayOfMonth, + "e": formatDayOfMonth, + "H": formatHour24, + "I": formatHour12, + "j": formatDayOfYear, + "L": formatMilliseconds, + "m": formatMonthNumber, + "M": formatMinutes, + "p": formatPeriod, + "S": formatSeconds, + "U": formatWeekNumberSunday, + "w": formatWeekdayNumber, + "W": formatWeekNumberMonday, + "x": null, + "X": null, + "y": formatYear, + "Y": formatFullYear, + "Z": formatZone, + "%": formatLiteralPercent + }; -var cursors = { - overlay: "crosshair", - selection: "move", - 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 utcFormats = { + "a": formatUTCShortWeekday, + "A": formatUTCWeekday, + "b": formatUTCShortMonth, + "B": formatUTCMonth, + "c": null, + "d": formatUTCDayOfMonth, + "e": formatUTCDayOfMonth, + "H": formatUTCHour24, + "I": formatUTCHour12, + "j": formatUTCDayOfYear, + "L": formatUTCMilliseconds, + "m": formatUTCMonthNumber, + "M": formatUTCMinutes, + "p": formatUTCPeriod, + "S": formatUTCSeconds, + "U": formatUTCWeekNumberSunday, + "w": formatUTCWeekdayNumber, + "W": formatUTCWeekNumberMonday, + "x": null, + "X": null, + "y": formatUTCYear, + "Y": formatUTCFullYear, + "Z": formatUTCZone, + "%": formatLiteralPercent + }; -var flipX = { - e: "w", - w: "e", - nw: "ne", - ne: "nw", - se: "sw", - sw: "se" -}; + var parses = { + "a": parseShortWeekday, + "A": parseWeekday, + "b": parseShortMonth, + "B": parseMonth, + "c": parseLocaleDateTime, + "d": parseDayOfMonth, + "e": parseDayOfMonth, + "H": parseHour24, + "I": parseHour24, + "j": parseDayOfYear, + "L": parseMilliseconds, + "m": parseMonthNumber, + "M": parseMinutes, + "p": parsePeriod, + "S": parseSeconds, + "U": parseWeekNumberSunday, + "w": parseWeekdayNumber, + "W": parseWeekNumberMonday, + "x": parseLocaleDate, + "X": parseLocaleTime, + "y": parseYear, + "Y": parseFullYear, + "Z": parseZone, + "%": parseLiteralPercent + }; -var flipY = { - n: "s", - s: "n", - nw: "sw", - ne: "se", - se: "ne", - sw: "nw" -}; + // These recursive directive definitions must be deferred. + formats.x = newFormat(locale_date, formats); + formats.X = newFormat(locale_time, formats); + formats.c = newFormat(locale_dateTime, formats); + utcFormats.x = newFormat(locale_date, utcFormats); + utcFormats.X = newFormat(locale_time, utcFormats); + utcFormats.c = newFormat(locale_dateTime, utcFormats); -var signsX = { - overlay: +1, - selection: +1, - n: null, - e: +1, - s: null, - w: -1, - nw: -1, - ne: +1, - se: +1, - sw: -1 -}; + function newFormat(specifier, formats) { + return function(date) { + var string = [], + i = -1, + j = 0, + n = specifier.length, + c, + pad, + format; -var signsY = { - overlay: +1, - selection: +1, - n: -1, - e: null, - s: +1, - w: null, - nw: -1, - ne: -1, - se: +1, - sw: +1 -}; + if (!(date instanceof Date)) date = new Date(+date); -function type$1(t) { - return {type: t}; -} + while (++i < n) { + if (specifier.charCodeAt(i) === 37) { + string.push(specifier.slice(j, i)); + if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); + else pad = c === "e" ? " " : "0"; + if (format = formats[c]) c = format(date, pad); + string.push(c); + j = i + 1; + } + } -// Ignore right-click, since that should open the context menu. -function defaultFilter$2() { - return !exports.event.button; -} + string.push(specifier.slice(j, i)); + return string.join(""); + }; + } -function defaultExtent$1() { - var svg = this.ownerSVGElement || this; - return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; -} + function newParse(specifier, newDate) { + return function(string) { + var d = newYear(1900), + i = parseSpecifier(d, specifier, string += "", 0); + if (i != string.length) return null; -// Like d3.local, but with the name “__brush” rather than auto-generated. -function local$1(node) { - while (!node.__brush) if (!(node = node.parentNode)) return; - return node.__brush; -} + // The am-pm flag is 0 for AM, and 1 for PM. + if ("p" in d) d.H = d.H % 12 + d.p * 12; -function empty$1(extent) { - return extent[0][0] === extent[1][0] - || extent[0][1] === extent[1][1]; -} + // Convert day-of-week and week-of-year to day-of-year. + if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "W" in d ? 1 : 0; + var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); + d.m = 0; + d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$$1 + 5) % 7 : d.w + d.U * 7 - (day$$1 + 6) % 7; + } -function brushSelection(node) { - var state = node.__brush; - return state ? state.dim.output(state.selection) : null; -} + // If a time zone is specified, all fields are interpreted as UTC and then + // offset according to the specified time zone. + if ("Z" in d) { + d.H += d.Z / 100 | 0; + d.M += d.Z % 100; + return utcDate(d); + } -function brushX() { - return brush$1(X); -} + // Otherwise, all fields are in local time. + return newDate(d); + }; + } -function brushY() { - return brush$1(Y); -} + function parseSpecifier(d, specifier, string, j) { + var i = 0, + n = specifier.length, + m = string.length, + c, + parse; -var brush = function() { - return brush$1(XY); -}; + while (i < n) { + if (j >= m) return -1; + c = specifier.charCodeAt(i++); + if (c === 37) { + c = specifier.charAt(i++); + parse = parses[c in pads ? specifier.charAt(i++) : c]; + if (!parse || ((j = parse(d, string, j)) < 0)) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } -function brush$1(dim) { - var extent = defaultExtent$1, - filter = defaultFilter$2, - listeners = dispatch(brush, "start", "brush", "end"), - handleSize = 6, - touchending; + return j; + } - function brush(group) { - var overlay = group - .property("__brush", initialize) - .selectAll(".overlay") - .data([type$1("overlay")]); + function parsePeriod(d, string, i) { + var n = periodRe.exec(string.slice(i)); + return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } - overlay.enter().append("rect") - .attr("class", "overlay") - .attr("pointer-events", "all") - .attr("cursor", cursors.overlay) - .merge(overlay) - .each(function() { - var extent = local$1(this).extent; - select(this) - .attr("x", extent[0][0]) - .attr("y", extent[0][1]) - .attr("width", extent[1][0] - extent[0][0]) - .attr("height", extent[1][1] - extent[0][1]); - }); + function parseShortWeekday(d, string, i) { + var n = shortWeekdayRe.exec(string.slice(i)); + return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } - group.selectAll(".selection") - .data([type$1("selection")]) - .enter().append("rect") - .attr("class", "selection") - .attr("cursor", cursors.selection) - .attr("fill", "#777") - .attr("fill-opacity", 0.3) - .attr("stroke", "#fff") - .attr("shape-rendering", "crispEdges"); + function parseWeekday(d, string, i) { + var n = weekdayRe.exec(string.slice(i)); + return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } - var handle = group.selectAll(".handle") - .data(dim.handles, function(d) { return d.type; }); + function parseShortMonth(d, string, i) { + var n = shortMonthRe.exec(string.slice(i)); + return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } - handle.exit().remove(); + function parseMonth(d, string, i) { + var n = monthRe.exec(string.slice(i)); + return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } - handle.enter().append("rect") - .attr("class", function(d) { return "handle handle--" + d.type; }) - .attr("cursor", function(d) { return cursors[d.type]; }); + function parseLocaleDateTime(d, string, i) { + return parseSpecifier(d, locale_dateTime, string, i); + } - group - .each(redraw) - .attr("fill", "none") - .attr("pointer-events", "all") - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") - .on("mousedown.brush touchstart.brush", started); + function parseLocaleDate(d, string, i) { + return parseSpecifier(d, locale_date, string, i); } - brush.move = function(group, selection$$1) { - if (group.selection) { - group - .on("start.brush", function() { emitter(this, arguments).beforestart().start(); }) - .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); }) - .tween("brush", function() { - var that = this, - state = that.__brush, - emit = emitter(that, arguments), - selection0 = state.selection, - selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent), - i = interpolate(selection0, selection1); + function parseLocaleTime(d, string, i) { + return parseSpecifier(d, locale_time, string, i); + } - function tween(t) { - state.selection = t === 1 && empty$1(selection1) ? null : i(t); - redraw.call(that); - emit.brush(); - } + function formatShortWeekday(d) { + return locale_shortWeekdays[d.getDay()]; + } - return selection0 && selection1 ? tween : tween(1); - }); - } else { - group - .each(function() { - var that = this, - args = arguments, - state = that.__brush, - selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent), - emit = emitter(that, args).beforestart(); + function formatWeekday(d) { + return locale_weekdays[d.getDay()]; + } - interrupt(that); - state.selection = selection1 == null || empty$1(selection1) ? null : selection1; - redraw.call(that); - emit.start().brush().end(); - }); - } - }; + function formatShortMonth(d) { + return locale_shortMonths[d.getMonth()]; + } - function redraw() { - var group = select(this), - selection$$1 = local$1(this).selection; + function formatMonth(d) { + return locale_months[d.getMonth()]; + } - if (selection$$1) { - group.selectAll(".selection") - .style("display", null) - .attr("x", selection$$1[0][0]) - .attr("y", selection$$1[0][1]) - .attr("width", selection$$1[1][0] - selection$$1[0][0]) - .attr("height", selection$$1[1][1] - selection$$1[0][1]); + function formatPeriod(d) { + return locale_periods[+(d.getHours() >= 12)]; + } - group.selectAll(".handle") - .style("display", null) - .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; }) - .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; }) - .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; }) - .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; }); - } + function formatUTCShortWeekday(d) { + return locale_shortWeekdays[d.getUTCDay()]; + } - else { - group.selectAll(".selection,.handle") - .style("display", "none") - .attr("x", null) - .attr("y", null) - .attr("width", null) - .attr("height", null); - } + function formatUTCWeekday(d) { + return locale_weekdays[d.getUTCDay()]; } - function emitter(that, args) { - return that.__brush.emitter || new Emitter(that, args); + function formatUTCShortMonth(d) { + return locale_shortMonths[d.getUTCMonth()]; } - function Emitter(that, args) { - this.that = that; - this.args = args; - this.state = that.__brush; - this.active = 0; + function formatUTCMonth(d) { + return locale_months[d.getUTCMonth()]; } - Emitter.prototype = { - beforestart: function() { - if (++this.active === 1) this.state.emitter = this, this.starting = true; - return this; - }, - start: function() { - if (this.starting) this.starting = false, this.emit("start"); - return this; + function formatUTCPeriod(d) { + return locale_periods[+(d.getUTCHours() >= 12)]; + } + + return { + format: function(specifier) { + var f = newFormat(specifier += "", formats); + f.toString = function() { return specifier; }; + return f; }, - brush: function() { - this.emit("brush"); - return this; + parse: function(specifier) { + var p = newParse(specifier += "", localDate); + p.toString = function() { return specifier; }; + return p; }, - end: function() { - if (--this.active === 0) delete this.state.emitter, this.emit("end"); - return this; + utcFormat: function(specifier) { + var f = newFormat(specifier += "", utcFormats); + f.toString = function() { return specifier; }; + return f; }, - emit: function(type) { - customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); + utcParse: function(specifier) { + var p = newParse(specifier, utcDate); + p.toString = function() { return specifier; }; + return p; } }; +} - function started() { - if (exports.event.touches) { if (exports.event.changedTouches.length < exports.event.touches.length) return noevent$2(); } - else if (touchending) return; - if (!filter.apply(this, arguments)) return; +var pads = {"-": "", "_": " ", "0": "0"}; +var numberRe = /^\s*\d+/; +var percentRe = /^%/; +var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - var that = this, - type = exports.event.target.__data__.type, - mode = (exports.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (exports.event.altKey ? MODE_CENTER : MODE_HANDLE), - signX = dim === Y ? null : signsX[type], - signY = dim === X ? null : signsY[type], - state = local$1(that), - extent = state.extent, - selection$$1 = state.selection, - W = extent[0][0], w0, w1, - N = extent[0][1], n0, n1, - E = extent[1][0], e0, e1, - S = extent[1][1], s0, s1, - dx, - dy, - moving, - shifting = signX && signY && exports.event.shiftKey, - lockX, - lockY, - point0 = mouse(that), - point = point0, - emit = emitter(that, arguments).beforestart(); +function pad(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 requote(s) { + return s.replace(requoteRe, "\\$&"); +} + +function formatRe(names) { + return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); +} - if (type === "overlay") { - state.selection = selection$$1 = [ - [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], - [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] - ]; - } else { - w0 = selection$$1[0][0]; - n0 = selection$$1[0][1]; - e0 = selection$$1[1][0]; - s0 = selection$$1[1][1]; - } +function formatLookup(names) { + var map = {}, i = -1, n = names.length; + while (++i < n) map[names[i].toLowerCase()] = i; + return map; +} - w1 = w0; - n1 = n0; - e1 = e0; - s1 = s0; +function parseWeekdayNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.w = +n[0], i + n[0].length) : -1; +} - var group = select(that) - .attr("pointer-events", "none"); +function parseWeekNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.U = +n[0], i + n[0].length) : -1; +} - var overlay = group.selectAll(".overlay") - .attr("cursor", cursors[type]); +function parseWeekNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.W = +n[0], i + n[0].length) : -1; +} - if (exports.event.touches) { - group - .on("touchmove.brush", moved, true) - .on("touchend.brush touchcancel.brush", ended, true); - } else { - var view = select(exports.event.view) - .on("keydown.brush", keydowned, true) - .on("keyup.brush", keyupped, true) - .on("mousemove.brush", moved, true) - .on("mouseup.brush", ended, true); +function parseFullYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 4)); + return n ? (d.y = +n[0], i + n[0].length) : -1; +} - dragDisable(exports.event.view); - } +function parseYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; +} - nopropagation$2(); - interrupt(that); - redraw.call(that); - emit.start(); +function parseZone(d, string, i) { + var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6)); + return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; +} - function moved() { - var point1 = mouse(that); - if (shifting && !lockX && !lockY) { - if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true; - else lockX = true; - } - point = point1; - moving = true; - noevent$2(); - move(); - } +function parseMonthNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.m = n[0] - 1, i + n[0].length) : -1; +} - function move() { - var t; +function parseDayOfMonth(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.d = +n[0], i + n[0].length) : -1; +} - dx = point[0] - point0[0]; - dy = point[1] - point0[1]; +function parseDayOfYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; +} - switch (mode) { - case MODE_SPACE: - case MODE_DRAG: { - if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; - if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; - break; - } - case MODE_HANDLE: { - if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; - else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; - if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; - else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; - break; - } - case MODE_CENTER: { - if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); - if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); - break; - } - } +function parseHour24(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.H = +n[0], i + n[0].length) : -1; +} - if (e1 < w1) { - signX *= -1; - t = w0, w0 = e0, e0 = t; - t = w1, w1 = e1, e1 = t; - if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]); - } +function parseMinutes(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.M = +n[0], i + n[0].length) : -1; +} - if (s1 < n1) { - signY *= -1; - t = n0, n0 = s0, s0 = t; - t = n1, n1 = s1, s1 = t; - if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]); - } +function parseSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.S = +n[0], i + n[0].length) : -1; +} - if (state.selection) selection$$1 = state.selection; // May be set by brush.move! - if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0]; - if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1]; +function parseMilliseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.L = +n[0], i + n[0].length) : -1; +} - if (selection$$1[0][0] !== w1 - || selection$$1[0][1] !== n1 - || selection$$1[1][0] !== e1 - || selection$$1[1][1] !== s1) { - state.selection = [[w1, n1], [e1, s1]]; - redraw.call(that); - emit.brush(); - } - } +function parseLiteralPercent(d, string, i) { + var n = percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; +} - function ended() { - nopropagation$2(); - if (exports.event.touches) { - if (exports.event.touches.length) return; - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! - group.on("touchmove.brush touchend.brush touchcancel.brush", null); - } else { - yesdrag(exports.event.view, moving); - view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); - } - group.attr("pointer-events", "all"); - overlay.attr("cursor", cursors.overlay); - if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)! - if (empty$1(selection$$1)) state.selection = null, redraw.call(that); - emit.end(); - } +function formatDayOfMonth(d, p) { + return pad(d.getDate(), p, 2); +} - function keydowned() { - switch (exports.event.keyCode) { - case 16: { // SHIFT - shifting = signX && signY; - break; - } - case 18: { // ALT - if (mode === MODE_HANDLE) { - if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; - if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; - mode = MODE_CENTER; - move(); - } - break; - } - case 32: { // SPACE; takes priority over ALT - if (mode === MODE_HANDLE || mode === MODE_CENTER) { - if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx; - if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy; - mode = MODE_SPACE; - overlay.attr("cursor", cursors.selection); - move(); - } - break; - } - default: return; - } - noevent$2(); - } +function formatHour24(d, p) { + return pad(d.getHours(), p, 2); +} - function keyupped() { - switch (exports.event.keyCode) { - case 16: { // SHIFT - if (shifting) { - lockX = lockY = shifting = false; - move(); - } - break; - } - case 18: { // ALT - if (mode === MODE_CENTER) { - if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; - if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; - mode = MODE_HANDLE; - move(); - } - break; - } - case 32: { // SPACE - if (mode === MODE_SPACE) { - if (exports.event.altKey) { - if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; - if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; - mode = MODE_CENTER; - } else { - if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; - if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; - mode = MODE_HANDLE; - } - overlay.attr("cursor", cursors[type]); - move(); - } - break; - } - default: return; - } - noevent$2(); - } - } +function formatHour12(d, p) { + return pad(d.getHours() % 12 || 12, p, 2); +} + +function formatDayOfYear(d, p) { + return pad(1 + day.count(year(d), d), p, 3); +} + +function formatMilliseconds(d, p) { + return pad(d.getMilliseconds(), p, 3); +} - function initialize() { - var state = this.__brush || {selection: null}; - state.extent = extent.apply(this, arguments); - state.dim = dim; - return state; - } +function formatMonthNumber(d, p) { + return pad(d.getMonth() + 1, p, 2); +} - brush.extent = function(_) { - return arguments.length ? (extent = typeof _ === "function" ? _ : constant$11([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent; - }; +function formatMinutes(d, p) { + return pad(d.getMinutes(), p, 2); +} - brush.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$11(!!_), brush) : filter; - }; +function formatSeconds(d, p) { + return pad(d.getSeconds(), p, 2); +} - brush.handleSize = function(_) { - return arguments.length ? (handleSize = +_, brush) : handleSize; - }; +function formatWeekNumberSunday(d, p) { + return pad(sunday.count(year(d), d), p, 2); +} - brush.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? brush : value; - }; +function formatWeekdayNumber(d) { + return d.getDay(); +} - return brush; +function formatWeekNumberMonday(d, p) { + return pad(monday.count(year(d), d), p, 2); } -var cos = Math.cos; -var sin = Math.sin; -var pi$3 = Math.PI; -var halfPi$2 = pi$3 / 2; -var tau$3 = pi$3 * 2; -var max$1 = Math.max; +function formatYear(d, p) { + return pad(d.getFullYear() % 100, p, 2); +} -function compareValue(compare) { - return function(a, b) { - return compare( - a.source.value + a.target.value, - b.source.value + b.target.value - ); - }; +function formatFullYear(d, p) { + return pad(d.getFullYear() % 10000, p, 4); } -var chord = function() { - var padAngle = 0, - sortGroups = null, - sortSubgroups = null, - sortChords = null; +function formatZone(d) { + var z = d.getTimezoneOffset(); + return (z > 0 ? "-" : (z *= -1, "+")) + + pad(z / 60 | 0, "0", 2) + + pad(z % 60, "0", 2); +} - function chord(matrix) { - var n = matrix.length, - groupSums = [], - groupIndex = range(n), - subgroupIndex = [], - chords = [], - groups = chords.groups = new Array(n), - subgroups = new Array(n * n), - k, - x, - x0, - dx, - i, - j; +function formatUTCDayOfMonth(d, p) { + return pad(d.getUTCDate(), p, 2); +} - // Compute the sum. - k = 0, i = -1; while (++i < n) { - x = 0, j = -1; while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(range(n)); - k += x; - } +function formatUTCHour24(d, p) { + return pad(d.getUTCHours(), p, 2); +} - // Sort groups… - if (sortGroups) groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); +function formatUTCHour12(d, p) { + return pad(d.getUTCHours() % 12 || 12, p, 2); +} - // Sort subgroups… - if (sortSubgroups) subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); +function formatUTCDayOfYear(d, p) { + return pad(1 + utcDay.count(utcYear(d), d), p, 3); +} - // Convert the sum to scaling factor for [0, 2pi]. - // TODO Allow start and end angle to be specified? - // TODO Allow padding to be specified as percentage? - k = max$1(0, tau$3 - padAngle * n) / k; - dx = k ? padAngle : tau$3 / n; +function formatUTCMilliseconds(d, p) { + return pad(d.getUTCMilliseconds(), p, 3); +} - // Compute the start and end angle for each group and subgroup. - // Note: Opera has a bug reordering object literal properties! - 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[dj * n + di] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: groupSums[di] - }; - x += dx; - } +function formatUTCMonthNumber(d, p) { + return pad(d.getUTCMonth() + 1, p, 2); +} - // Generate chords for each (non-empty) subgroup-subgroup link. - i = -1; while (++i < n) { - j = i - 1; while (++j < n) { - var source = subgroups[j * n + i], - target = subgroups[i * n + j]; - if (source.value || target.value) { - chords.push(source.value < target.value - ? {source: target, target: source} - : {source: source, target: target}); - } - } - } +function formatUTCMinutes(d, p) { + return pad(d.getUTCMinutes(), p, 2); +} - return sortChords ? chords.sort(sortChords) : chords; - } +function formatUTCSeconds(d, p) { + return pad(d.getUTCSeconds(), p, 2); +} - chord.padAngle = function(_) { - return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle; - }; +function formatUTCWeekNumberSunday(d, p) { + return pad(utcSunday.count(utcYear(d), d), p, 2); +} - chord.sortGroups = function(_) { - return arguments.length ? (sortGroups = _, chord) : sortGroups; - }; +function formatUTCWeekdayNumber(d) { + return d.getUTCDay(); +} - chord.sortSubgroups = function(_) { - return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; - }; +function formatUTCWeekNumberMonday(d, p) { + return pad(utcMonday.count(utcYear(d), d), p, 2); +} - chord.sortChords = function(_) { - return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; - }; +function formatUTCYear(d, p) { + return pad(d.getUTCFullYear() % 100, p, 2); +} - return chord; -}; +function formatUTCFullYear(d, p) { + return pad(d.getUTCFullYear() % 10000, p, 4); +} -var slice$5 = Array.prototype.slice; +function formatUTCZone() { + return "+0000"; +} -var constant$12 = function(x) { - return function() { - return x; - }; -}; +function formatLiteralPercent() { + return "%"; +} -function defaultSource(d) { - return d.source; +var locale$2; + + + + + +defaultLocale$1({ + dateTime: "%x, %X", + date: "%-m/%-d/%Y", + time: "%-I:%M:%S %p", + 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"] +}); + +function defaultLocale$1(definition) { + locale$2 = formatLocale$1(definition); + exports.timeFormat = locale$2.format; + exports.timeParse = locale$2.parse; + exports.utcFormat = locale$2.utcFormat; + exports.utcParse = locale$2.utcParse; + return locale$2; } -function defaultTarget(d) { - return d.target; +var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; + +function formatIsoNative(date) { + return date.toISOString(); } -function defaultRadius$1(d) { - return d.radius; +var formatIso = Date.prototype.toISOString + ? formatIsoNative + : exports.utcFormat(isoSpecifier); + +function parseIsoNative(string) { + var date = new Date(string); + return isNaN(date) ? null : date; } -function defaultStartAngle(d) { - return d.startAngle; +var parseIso = +new Date("2000-01-01T00:00:00.000Z") + ? parseIsoNative + : exports.utcParse(isoSpecifier); + +var durationSecond = 1000; +var durationMinute = durationSecond * 60; +var durationHour = durationMinute * 60; +var durationDay = durationHour * 24; +var durationWeek = durationDay * 7; +var durationMonth = durationDay * 30; +var durationYear = durationDay * 365; + +function date$1(t) { + return new Date(t); } -function defaultEndAngle(d) { - return d.endAngle; +function number$2(t) { + return t instanceof Date ? +t : +new Date(+t); } -var ribbon = function() { - var source = defaultSource, - target = defaultTarget, - radius = defaultRadius$1, - startAngle = defaultStartAngle, - endAngle = defaultEndAngle, - context = null; +function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) { + var scale = continuous(deinterpolateLinear, reinterpolate), + invert = scale.invert, + domain = scale.domain; - function ribbon() { - var buffer, - argv = slice$5.call(arguments), - s = source.apply(this, argv), - t = target.apply(this, argv), - sr = +radius.apply(this, (argv[0] = s, argv)), - sa0 = startAngle.apply(this, argv) - halfPi$2, - sa1 = endAngle.apply(this, argv) - halfPi$2, - sx0 = sr * cos(sa0), - sy0 = sr * sin(sa0), - tr = +radius.apply(this, (argv[0] = t, argv)), - ta0 = startAngle.apply(this, argv) - halfPi$2, - ta1 = endAngle.apply(this, argv) - halfPi$2; + var formatMillisecond = format(".%L"), + formatSecond = format(":%S"), + formatMinute = format("%I:%M"), + formatHour = format("%I %p"), + formatDay = format("%a %d"), + formatWeek = format("%b %d"), + formatMonth = format("%B"), + formatYear = format("%Y"); - if (!context) context = buffer = path(); + var tickIntervals = [ + [second$$1, 1, durationSecond], + [second$$1, 5, 5 * durationSecond], + [second$$1, 15, 15 * durationSecond], + [second$$1, 30, 30 * durationSecond], + [minute$$1, 1, durationMinute], + [minute$$1, 5, 5 * durationMinute], + [minute$$1, 15, 15 * durationMinute], + [minute$$1, 30, 30 * durationMinute], + [ hour$$1, 1, durationHour ], + [ hour$$1, 3, 3 * durationHour ], + [ hour$$1, 6, 6 * durationHour ], + [ hour$$1, 12, 12 * durationHour ], + [ day$$1, 1, durationDay ], + [ day$$1, 2, 2 * durationDay ], + [ week, 1, durationWeek ], + [ month$$1, 1, durationMonth ], + [ month$$1, 3, 3 * durationMonth ], + [ year$$1, 1, durationYear ] + ]; - context.moveTo(sx0, sy0); - context.arc(0, 0, sr, sa0, sa1); - if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? - context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); - context.arc(0, 0, tr, ta0, ta1); + function tickFormat(date) { + return (second$$1(date) < date ? formatMillisecond + : minute$$1(date) < date ? formatSecond + : hour$$1(date) < date ? formatMinute + : day$$1(date) < date ? formatHour + : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek) + : year$$1(date) < date ? formatMonth + : formatYear)(date); + } + + function tickInterval(interval, start, stop, step) { + if (interval == null) interval = 10; + + // If a desired tick count is specified, pick a reasonable tick interval + // based on the extent of the domain and a rough estimate of tick size. + // Otherwise, assume interval is already a time interval and use it. + if (typeof interval === "number") { + var target = Math.abs(stop - start) / interval, + i = bisector(function(i) { return i[2]; }).right(tickIntervals, target); + if (i === tickIntervals.length) { + step = tickStep(start / durationYear, stop / durationYear, interval); + interval = year$$1; + } else if (i) { + i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; + step = i[1]; + interval = i[0]; + } else { + step = tickStep(start, stop, interval); + interval = millisecond$$1; + } } - context.quadraticCurveTo(0, 0, sx0, sy0); - context.closePath(); - if (buffer) return context = null, buffer + "" || null; + return step == null ? interval : interval.every(step); } - ribbon.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant$12(+_), ribbon) : radius; + scale.invert = function(y) { + return new Date(invert(y)); }; - ribbon.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : startAngle; + scale.domain = function(_) { + return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1); }; - ribbon.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : endAngle; + scale.ticks = function(interval, step) { + var d = domain(), + t0 = d[0], + t1 = d[d.length - 1], + r = t1 < t0, + t; + if (r) t = t0, t0 = t1, t1 = t; + t = tickInterval(interval, t0, t1, step); + t = t ? t.range(t0, t1 + 1) : []; // inclusive stop + return r ? t.reverse() : t; }; - ribbon.source = function(_) { - return arguments.length ? (source = _, ribbon) : source; + scale.tickFormat = function(count, specifier) { + return specifier == null ? tickFormat : format(specifier); }; - ribbon.target = function(_) { - return arguments.length ? (target = _, ribbon) : target; + scale.nice = function(interval, step) { + var d = domain(); + return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) + ? domain(nice(d, interval)) + : scale; }; - ribbon.context = function(_) { - return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; + scale.copy = function() { + return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format)); }; - return ribbon; -}; - -// Adds floating point numbers with twice the normal precision. -// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and -// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) -// 305–363 (1997). -// Code adapted from GeographicLib by Charles F. F. Karney, -// http://geographiclib.sourceforge.net/ - -var adder = function() { - return new Adder; -}; - -function Adder() { - this.reset(); + return scale; } -Adder.prototype = { - constructor: Adder, - reset: function() { - this.s = // rounded value - this.t = 0; // exact error - }, - add: function(y) { - add$1(temp, y, this.t); - add$1(this, temp.s, this.s); - if (this.s) this.t += temp.t; - else this.s = temp.t; - }, - valueOf: function() { - return this.s; - } +var time = function() { + return calendar(year, month, sunday, day, hour, minute, second, millisecond, exports.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); }; -var temp = new Adder; - -function add$1(adder, a, b) { - var x = adder.s = a + b, - bv = x - a, - av = x - bv; - adder.t = (a - av) + (b - bv); -} - -var epsilon$4 = 1e-6; -var epsilon2$2 = 1e-12; -var pi$4 = Math.PI; -var halfPi$3 = pi$4 / 2; -var quarterPi = pi$4 / 4; -var tau$4 = pi$4 * 2; +var utcTime = function() { + return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, exports.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]); +}; -var degrees$1 = 180 / pi$4; -var radians = pi$4 / 180; +var colors = function(s) { + return s.match(/.{6}/g).map(function(x) { + return "#" + x; + }); +}; -var abs = Math.abs; -var atan = Math.atan; -var atan2 = Math.atan2; -var cos$1 = Math.cos; -var ceil = Math.ceil; -var exp = Math.exp; +var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); -var log$1 = Math.log; -var pow$1 = Math.pow; -var sin$1 = Math.sin; -var sign$1 = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; -var sqrt$1 = Math.sqrt; -var tan = Math.tan; +var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); -function acos(x) { - return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x); -} +var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); -function asin$1(x) { - return x > 1 ? halfPi$3 : x < -1 ? -halfPi$3 : Math.asin(x); -} +var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); -function haversin(x) { - return (x = sin$1(x / 2)) * x; -} +var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0)); -function noop$2() {} +var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); -function streamGeometry(geometry, stream) { - if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { - streamGeometryType[geometry.type](geometry, stream); - } -} +var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); -var streamObjectType = { - Feature: function(feature, stream) { - streamGeometry(feature.geometry, stream); - }, - FeatureCollection: function(object, stream) { - var features = object.features, i = -1, n = features.length; - while (++i < n) streamGeometry(features[i].geometry, stream); - } -}; +var rainbow = cubehelix(); -var streamGeometryType = { - Sphere: function(object, stream) { - stream.sphere(); - }, - Point: function(object, stream) { - object = object.coordinates; - stream.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, stream) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); - }, - LineString: function(object, stream) { - streamLine(object.coordinates, stream, 0); - }, - MultiLineString: function(object, stream) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) streamLine(coordinates[i], stream, 0); - }, - Polygon: function(object, stream) { - streamPolygon(object.coordinates, stream); - }, - MultiPolygon: function(object, stream) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) streamPolygon(coordinates[i], stream); - }, - GeometryCollection: function(object, stream) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) streamGeometry(geometries[i], stream); - } +var rainbow$1 = function(t) { + if (t < 0 || t > 1) t -= Math.floor(t); + var ts = Math.abs(t - 0.5); + rainbow.h = 360 * t - 100; + rainbow.s = 1.5 - 1.5 * ts; + rainbow.l = 0.8 - 0.9 * ts; + return rainbow + ""; }; -function streamLine(coordinates, stream, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - stream.lineStart(); - while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); - stream.lineEnd(); +function ramp(range) { + var n = range.length; + return function(t) { + return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + }; } -function streamPolygon(coordinates, stream) { - var i = -1, n = coordinates.length; - stream.polygonStart(); - while (++i < n) streamLine(coordinates[i], stream, 1); - stream.polygonEnd(); -} +var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); -var geoStream = function(object, stream) { - if (object && streamObjectType.hasOwnProperty(object.type)) { - streamObjectType[object.type](object, stream); - } else { - streamGeometry(object, stream); - } -}; +var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); -var areaRingSum = adder(); +var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); -var areaSum = adder(); -var lambda00; -var phi00; -var lambda0; -var cosPhi0; -var sinPhi0; +var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); -var areaStream = { - point: noop$2, - lineStart: noop$2, - lineEnd: noop$2, - polygonStart: function() { - areaRingSum.reset(); - areaStream.lineStart = areaRingStart; - areaStream.lineEnd = areaRingEnd; - }, - polygonEnd: function() { - var areaRing = +areaRingSum; - areaSum.add(areaRing < 0 ? tau$4 + areaRing : areaRing); - this.lineStart = this.lineEnd = this.point = noop$2; - }, - sphere: function() { - areaSum.add(tau$4); - } -}; +function sequential(interpolator) { + var x0 = 0, + x1 = 1, + clamp = false; -function areaRingStart() { - areaStream.point = areaPointFirst; -} + function scale(x) { + var t = (x - x0) / (x1 - x0); + return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t); + } -function areaRingEnd() { - areaPoint(lambda00, phi00); -} + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1]; + }; -function areaPointFirst(lambda, phi) { - areaStream.point = areaPoint; - lambda00 = lambda, phi00 = phi; - lambda *= radians, phi *= radians; - lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi); -} + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, scale) : clamp; + }; -function areaPoint(lambda, phi) { - lambda *= radians, phi *= radians; - phi = phi / 2 + quarterPi; // half the angular distance from south pole + scale.interpolator = function(_) { + return arguments.length ? (interpolator = _, scale) : interpolator; + }; - // Spherical excess E for a spherical triangle with vertices: south pole, - // previous point, current point. Uses a formula derived from Cagnoli’s - // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). - var dLambda = lambda - lambda0, - sdLambda = dLambda >= 0 ? 1 : -1, - adLambda = sdLambda * dLambda, - cosPhi = cos$1(phi), - sinPhi = sin$1(phi), - k = sinPhi0 * sinPhi, - u = cosPhi0 * cosPhi + k * cos$1(adLambda), - v = k * sdLambda * sin$1(adLambda); - areaRingSum.add(atan2(v, u)); + scale.copy = function() { + return sequential(interpolator).domain([x0, x1]).clamp(clamp); + }; - // Advance the previous points. - lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; + return linearish(scale); } -var area$2 = function(object) { - areaSum.reset(); - geoStream(object, areaStream); - return areaSum * 2; +var constant$10 = function(x) { + return function constant() { + return x; + }; }; -function spherical(cartesian) { - return [atan2(cartesian[1], cartesian[0]), asin$1(cartesian[2])]; +var epsilon$3 = 1e-12; +var pi$4 = Math.PI; +var halfPi$3 = pi$4 / 2; +var tau$4 = 2 * pi$4; + +function arcInnerRadius(d) { + return d.innerRadius; } -function cartesian(spherical) { - var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi); - return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)]; +function arcOuterRadius(d) { + return d.outerRadius; } -function cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +function arcStartAngle(d) { + return d.startAngle; } -function 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 arcEndAngle(d) { + return d.endAngle; } -// TODO return a -function cartesianAddInPlace(a, b) { - a[0] += b[0], a[1] += b[1], a[2] += b[2]; +function arcPadAngle(d) { + return d && d.padAngle; // Note: optional! } -function cartesianScale(vector, k) { - return [vector[0] * k, vector[1] * k, vector[2] * k]; +function asin$1(x) { + return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x); } -// TODO return d -function cartesianNormalizeInPlace(d) { - var l = sqrt$1(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l, d[1] /= l, d[2] /= l; +function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { + var x10 = x1 - x0, y10 = y1 - y0, + x32 = x3 - x2, y32 = y3 - y2, + t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); + return [x0 + t * x10, y0 + t * y10]; } -var lambda0$1; -var phi0; -var lambda1; -var phi1; -var lambda2; -var lambda00$1; -var phi00$1; -var p0; -var deltaSum = adder(); -var ranges; -var range$1; +// Compute perpendicular offset line of length rc. +// http://mathworld.wolfram.com/Circle-LineIntersection.html +function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { + var x01 = x0 - x1, + y01 = y0 - y1, + lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), + ox = lo * y01, + oy = -lo * x01, + x11 = x0 + ox, + y11 = y0 + oy, + x10 = x1 + ox, + y10 = y1 + oy, + x00 = (x11 + x10) / 2, + y00 = (y11 + y10) / 2, + dx = x10 - x11, + dy = y10 - y11, + d2 = dx * dx + dy * dy, + r = r1 - rc, + D = x11 * y10 - x10 * y11, + 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 - x00, + dy0 = cy0 - y00, + dx1 = cx1 - x00, + dy1 = cy1 - y00; -var boundsStream = { - point: boundsPoint, - lineStart: boundsLineStart, - lineEnd: boundsLineEnd, - polygonStart: function() { - boundsStream.point = boundsRingPoint; - boundsStream.lineStart = boundsRingStart; - boundsStream.lineEnd = boundsRingEnd; - deltaSum.reset(); - areaStream.polygonStart(); - }, - polygonEnd: function() { - areaStream.polygonEnd(); - boundsStream.point = boundsPoint; - boundsStream.lineStart = boundsLineStart; - boundsStream.lineEnd = boundsLineEnd; - if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); - else if (deltaSum > epsilon$4) phi1 = 90; - else if (deltaSum < -epsilon$4) phi0 = -90; - range$1[0] = lambda0$1, range$1[1] = lambda1; - } -}; + // Pick the closer of the two intersection points. + // TODO Is there a faster way to determine which intersection to use? + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + + return { + cx: cx0, + cy: cy0, + x01: -ox, + y01: -oy, + x11: cx0 * (r1 / r - 1), + y11: cy0 * (r1 / r - 1) + }; +} + +var arc = function() { + var innerRadius = arcInnerRadius, + outerRadius = arcOuterRadius, + cornerRadius = constant$10(0), + padRadius = null, + startAngle = arcStartAngle, + endAngle = arcEndAngle, + padAngle = arcPadAngle, + context = null; + + function arc() { + var buffer, + r, + r0 = +innerRadius.apply(this, arguments), + r1 = +outerRadius.apply(this, arguments), + a0 = startAngle.apply(this, arguments) - halfPi$3, + a1 = endAngle.apply(this, arguments) - halfPi$3, + da = Math.abs(a1 - a0), + cw = a1 > a0; + + if (!context) context = buffer = path(); + + // Ensure that the outer radius is always larger than the inner radius. + if (r1 < r0) r = r1, r1 = r0, r0 = r; + + // Is it a point? + if (!(r1 > epsilon$3)) context.moveTo(0, 0); + + // Or is it a circle or annulus? + else if (da > tau$4 - epsilon$3) { + context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0)); + context.arc(0, 0, r1, a0, a1, !cw); + if (r0 > epsilon$3) { + context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1)); + context.arc(0, 0, r0, a1, a0, cw); + } + } + + // Or is it a circular or annular sector? + else { + var a01 = a0, + a11 = a1, + a00 = a0, + a10 = a1, + da0 = da, + da1 = da, + ap = padAngle.apply(this, arguments) / 2, + rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)), + rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), + rc0 = rc, + rc1 = rc, + t0, + t1; + + // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. + if (rp > epsilon$3) { + var p0 = asin$1(rp / r0 * Math.sin(ap)), + p1 = asin$1(rp / r1 * Math.sin(ap)); + if ((da0 -= p0 * 2) > epsilon$3) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; + else da0 = 0, a00 = a10 = (a0 + a1) / 2; + if ((da1 -= p1 * 2) > epsilon$3) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; + else da1 = 0, a01 = a11 = (a0 + a1) / 2; + } + + var x01 = r1 * Math.cos(a01), + y01 = r1 * Math.sin(a01), + x10 = r0 * Math.cos(a10), + y10 = r0 * Math.sin(a10); + + // Apply rounded corners? + if (rc > epsilon$3) { + var x11 = r1 * Math.cos(a11), + y11 = r1 * Math.sin(a11), + x00 = r0 * Math.cos(a00), + y00 = r0 * Math.sin(a00); + + // Restrict the corner radius according to the sector angle. + if (da < pi$4) { + var oc = da0 > epsilon$3 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], + ax = x01 - oc[0], + ay = y01 - oc[1], + bx = x11 - oc[0], + by = y11 - 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)); + } + } -function boundsPoint(lambda, phi) { - ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]); - if (phi < phi0) phi0 = phi; - if (phi > phi1) phi1 = phi; -} + // Is the sector collapsed to a line? + if (!(da1 > epsilon$3)) context.moveTo(x01, y01); -function linePoint(lambda, phi) { - var p = cartesian([lambda * radians, phi * radians]); - if (p0) { - var normal = cartesianCross(p0, p), - equatorial = [normal[1], -normal[0], 0], - inflection = cartesianCross(equatorial, normal); - cartesianNormalizeInPlace(inflection); - inflection = spherical(inflection); - var delta = lambda - lambda2, - sign$$1 = delta > 0 ? 1 : -1, - lambdai = inflection[0] * degrees$1 * sign$$1, - phii, - antimeridian = abs(delta) > 180; - if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { - phii = inflection[1] * degrees$1; - if (phii > phi1) phi1 = phii; - } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { - phii = -inflection[1] * degrees$1; - if (phii < phi0) phi0 = phii; - } else { - if (phi < phi0) phi0 = phi; - if (phi > phi1) phi1 = phi; - } - if (antimeridian) { - if (lambda < lambda2) { - if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; - } else { - if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + // Does the sector’s outer ring have rounded corners? + else if (rc1 > epsilon$3) { + t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); + t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); + + context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); + context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); + context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); + } } - } else { - if (lambda1 >= lambda0$1) { - if (lambda < lambda0$1) lambda0$1 = lambda; - if (lambda > lambda1) lambda1 = lambda; - } else { - if (lambda > lambda2) { - if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; - } else { - if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + + // Or is the outer ring just a circular arc? + else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); + + // Is there no inner ring, and it’s a circular sector? + // Or perhaps it’s an annular sector collapsed due to padding? + if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) context.lineTo(x10, y10); + + // Does the sector’s inner ring (or point) have rounded corners? + else if (rc0 > epsilon$3) { + t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); + t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); + + context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); + context.arc(0, 0, r0, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); + context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); } } - } - } else { - boundsPoint(lambda, phi); - } - p0 = p, lambda2 = lambda; -} -function boundsLineStart() { - boundsStream.point = linePoint; -} + // Or is the inner ring just a circular arc? + else context.arc(0, 0, r0, a10, a00, cw); + } -function boundsLineEnd() { - range$1[0] = lambda0$1, range$1[1] = lambda1; - boundsStream.point = boundsPoint; - p0 = null; -} + context.closePath(); -function boundsRingPoint(lambda, phi) { - if (p0) { - var delta = lambda - lambda2; - deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); - } else { - lambda00$1 = lambda, phi00$1 = phi; + if (buffer) return context = null, buffer + "" || null; } - areaStream.point(lambda, phi); - linePoint(lambda, phi); -} -function boundsRingStart() { - areaStream.lineStart(); -} + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, + a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2; + return [Math.cos(a) * r, Math.sin(a) * r]; + }; -function boundsRingEnd() { - boundsRingPoint(lambda00$1, phi00$1); - areaStream.lineEnd(); - if (abs(deltaSum) > epsilon$4) lambda0$1 = -(lambda1 = 180); - range$1[0] = lambda0$1, range$1[1] = lambda1; - p0 = null; -} + arc.innerRadius = function(_) { + return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : innerRadius; + }; -// Finds the left-right distance between two longitudes. -// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want -// the distance between ±180° to be 360°. -function angle(lambda0, lambda1) { - return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; -} + arc.outerRadius = function(_) { + return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : outerRadius; + }; -function rangeCompare(a, b) { - return a[0] - b[0]; -} + arc.cornerRadius = function(_) { + return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : cornerRadius; + }; -function rangeContains(range, x) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; -} + arc.padRadius = function(_) { + return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), arc) : padRadius; + }; -var bounds = function(feature) { - var i, n, a, b, merged, deltaMax, delta; + arc.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : startAngle; + }; - phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); - ranges = []; - geoStream(feature, boundsStream); + arc.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : endAngle; + }; - // First, sort ranges by their minimum longitudes. - if (n = ranges.length) { - ranges.sort(rangeCompare); + arc.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : padAngle; + }; - // Then, merge any ranges that overlap. - for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { - b = ranges[i]; - if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { - 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); - } - } + arc.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), arc) : context; + }; - // Finally, find the largest gap between the merged ranges. - // The final bounding box will be the inverse of this gap. - for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { - b = merged[i]; - if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; + return arc; +}; + +function Linear(context) { + this._context = context; +} + +Linear.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: this._context.lineTo(x, y); break; } } +}; - ranges = range$1 = null; - - return lambda0$1 === Infinity || phi0 === Infinity - ? [[NaN, NaN], [NaN, NaN]] - : [[lambda0$1, phi0], [lambda1, phi1]]; +var curveLinear = function(context) { + return new Linear(context); }; -var W0; -var W1; -var X0; -var Y0; -var Z0; -var X1; -var Y1; -var Z1; -var X2; -var Y2; -var Z2; -var lambda00$2; -var phi00$2; -var x0; -var y0; -var z0; // previous point +function x$3(p) { + return p[0]; +} -var centroidStream = { - sphere: noop$2, - point: centroidPoint, - lineStart: centroidLineStart, - lineEnd: centroidLineEnd, - polygonStart: function() { - centroidStream.lineStart = centroidRingStart; - centroidStream.lineEnd = centroidRingEnd; - }, - polygonEnd: function() { - centroidStream.lineStart = centroidLineStart; - centroidStream.lineEnd = centroidLineEnd; +function y$3(p) { + return p[1]; +} + +var line = function() { + var x$$1 = x$3, + y$$1 = y$3, + defined = constant$10(true), + context = null, + curve = curveLinear, + output = null; + + function line(data) { + var i, + n = data.length, + d, + defined0 = false, + buffer; + + if (context == null) output = curve(buffer = path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) output.lineStart(); + else output.lineEnd(); + } + if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); + } + + if (buffer) return output = null, buffer + "" || null; } + + line.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : x$$1; + }; + + line.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : y$$1; + }; + + line.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), line) : defined; + }; + + line.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; + }; + + line.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; + }; + + return line; }; -// Arithmetic mean of Cartesian vectors. -function centroidPoint(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi); - centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)); -} +var area$2 = function() { + var x0 = x$3, + x1 = null, + y0 = constant$10(0), + y1 = y$3, + defined = constant$10(true), + context = null, + curve = curveLinear, + output = null; -function centroidPointCartesian(x, y, z) { - ++W0; - X0 += (x - X0) / W0; - Y0 += (y - Y0) / W0; - Z0 += (z - Z0) / W0; -} + function area(data) { + var i, + j, + k, + n = data.length, + d, + defined0 = false, + buffer, + x0z = new Array(n), + y0z = new Array(n); -function centroidLineStart() { - centroidStream.point = centroidLinePointFirst; -} + if (context == null) output = curve(buffer = path()); -function centroidLinePointFirst(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi); - x0 = cosPhi * cos$1(lambda); - y0 = cosPhi * sin$1(lambda); - z0 = sin$1(phi); - centroidStream.point = centroidLinePoint; - centroidPointCartesian(x0, y0, z0); -} + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) { + j = i; + output.areaStart(); + output.lineStart(); + } else { + output.lineEnd(); + output.lineStart(); + for (k = i - 1; k >= j; --k) { + output.point(x0z[k], y0z[k]); + } + output.lineEnd(); + output.areaEnd(); + } + } + if (defined0) { + x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); + output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); + } + } -function centroidLinePoint(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi), - x = cosPhi * cos$1(lambda), - y = cosPhi * sin$1(lambda), - z = sin$1(phi), - w = atan2(sqrt$1((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - W1 += w; - X1 += w * (x0 + (x0 = x)); - Y1 += w * (y0 + (y0 = y)); - Z1 += w * (z0 + (z0 = z)); - centroidPointCartesian(x0, y0, z0); -} + if (buffer) return output = null, buffer + "" || null; + } -function centroidLineEnd() { - centroidStream.point = centroidPoint; -} + function arealine() { + return line().defined(defined).curve(curve).context(context); + } -// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, -// J. Applied Mechanics 42, 239 (1975). -function centroidRingStart() { - centroidStream.point = centroidRingPointFirst; -} + area.x = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), x1 = null, area) : x0; + }; -function centroidRingEnd() { - centroidRingPoint(lambda00$2, phi00$2); - centroidStream.point = centroidPoint; -} + area.x0 = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), area) : x0; + }; -function centroidRingPointFirst(lambda, phi) { - lambda00$2 = lambda, phi00$2 = phi; - lambda *= radians, phi *= radians; - centroidStream.point = centroidRingPoint; - var cosPhi = cos$1(phi); - x0 = cosPhi * cos$1(lambda); - y0 = cosPhi * sin$1(lambda); - z0 = sin$1(phi); - centroidPointCartesian(x0, y0, z0); -} + area.x1 = function(_) { + return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : x1; + }; -function centroidRingPoint(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi), - x = cosPhi * cos$1(lambda), - y = cosPhi * sin$1(lambda), - z = sin$1(phi), - cx = y0 * z - z0 * y, - cy = z0 * x - x0 * z, - cz = x0 * y - y0 * x, - m = sqrt$1(cx * cx + cy * cy + cz * cz), - u = x0 * x + y0 * y + z0 * z, - v = m && -acos(u) / m, // area weight - w = atan2(m, u); // line weight - X2 += v * cx; - Y2 += v * cy; - Z2 += v * cz; - W1 += w; - X1 += w * (x0 + (x0 = x)); - Y1 += w * (y0 + (y0 = y)); - Z1 += w * (z0 + (z0 = z)); - centroidPointCartesian(x0, y0, z0); -} + area.y = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), y1 = null, area) : y0; + }; -var centroid$1 = function(object) { - W0 = W1 = - X0 = Y0 = Z0 = - X1 = Y1 = Z1 = - X2 = Y2 = Z2 = 0; - geoStream(object, centroidStream); + area.y0 = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), area) : y0; + }; - var x = X2, - y = Y2, - z = Z2, - m = x * x + y * y + z * z; + area.y1 = function(_) { + return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : y1; + }; - // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. - if (m < epsilon2$2) { - x = X1, y = Y1, z = Z1; - // If the feature has zero length, fall back to arithmetic mean of point vectors. - if (W1 < epsilon$4) x = X0, y = Y0, z = Z0; - m = x * x + y * y + z * z; - // If the feature still has an undefined ccentroid, then return. - if (m < epsilon2$2) return [NaN, NaN]; - } + area.lineX0 = + area.lineY0 = function() { + return arealine().x(x0).y(y0); + }; - return [atan2(y, x) * degrees$1, asin$1(z / sqrt$1(m)) * degrees$1]; -}; + area.lineY1 = function() { + return arealine().x(x0).y(y1); + }; -var constant$13 = function(x) { - return function() { - return x; + area.lineX1 = function() { + return arealine().x(x1).y(y0); }; -}; -var compose = function(a, b) { + area.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), area) : defined; + }; - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } + area.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; + }; - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); + area.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; }; - return compose; + return area; }; -function rotationIdentity(lambda, phi) { - return [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi]; -} +var descending$1 = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +}; -rotationIdentity.invert = rotationIdentity; +var identity$7 = function(d) { + return d; +}; -function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { - return (deltaLambda %= tau$4) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) - : rotationLambda(deltaLambda)) - : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) - : rotationIdentity); -} +var pie = function() { + var value = identity$7, + sortValues = descending$1, + sort = null, + startAngle = constant$10(0), + endAngle = constant$10(tau$4), + padAngle = constant$10(0); -function forwardRotationLambda(deltaLambda) { - return function(lambda, phi) { - return lambda += deltaLambda, [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi]; - }; -} + function pie(data) { + var i, + n = data.length, + j, + k, + sum = 0, + index = new Array(n), + arcs = new Array(n), + a0 = +startAngle.apply(this, arguments), + da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)), + a1, + p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), + pa = p * (da < 0 ? -1 : 1), + v; -function rotationLambda(deltaLambda) { - var rotation = forwardRotationLambda(deltaLambda); - rotation.invert = forwardRotationLambda(-deltaLambda); - return rotation; -} + for (i = 0; i < n; ++i) { + if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { + sum += v; + } + } -function rotationPhiGamma(deltaPhi, deltaGamma) { - var cosDeltaPhi = cos$1(deltaPhi), - sinDeltaPhi = sin$1(deltaPhi), - cosDeltaGamma = cos$1(deltaGamma), - sinDeltaGamma = sin$1(deltaGamma); + // Optionally sort the arcs by previously-computed values or by data. + if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); + else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); + + // Compute the arcs! They are stored in the original data's order. + for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { + j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { + data: data[j], + index: i, + value: v, + startAngle: a0, + endAngle: a1, + padAngle: p + }; + } - function rotation(lambda, phi) { - var cosPhi = cos$1(phi), - x = cos$1(lambda) * cosPhi, - y = sin$1(lambda) * cosPhi, - z = sin$1(phi), - k = z * cosDeltaPhi + x * sinDeltaPhi; - return [ - atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), - asin$1(k * cosDeltaGamma + y * sinDeltaGamma) - ]; + return arcs; } - rotation.invert = function(lambda, phi) { - var cosPhi = cos$1(phi), - x = cos$1(lambda) * cosPhi, - y = sin$1(lambda) * cosPhi, - z = sin$1(phi), - k = z * cosDeltaGamma - y * sinDeltaGamma; - return [ - atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), - asin$1(k * cosDeltaPhi - x * sinDeltaPhi) - ]; + pie.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), pie) : value; }; - return rotation; -} + pie.sortValues = function(_) { + return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; + }; -var rotation = function(rotate) { - rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); + pie.sort = function(_) { + return arguments.length ? (sort = _, sortValues = null, pie) : sort; + }; - function forward(coordinates) { - coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); - return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; - } + pie.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : startAngle; + }; - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); - return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + pie.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : endAngle; }; - return forward; + pie.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : padAngle; + }; + + return pie; }; -// Generates a circle centered at [0°, 0°], with a given radius and precision. -function circleStream(stream, radius, delta, direction, t0, t1) { - if (!delta) return; - var cosRadius = cos$1(radius), - sinRadius = sin$1(radius), - step = direction * delta; - if (t0 == null) { - t0 = radius + direction * tau$4; - t1 = radius - step / 2; - } else { - t0 = circleRadius(cosRadius, t0); - t1 = circleRadius(cosRadius, t1); - if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$4; - } - for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { - point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]); - stream.point(point[0], point[1]); - } -} +var curveRadialLinear = curveRadial(curveLinear); -// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. -function circleRadius(cosRadius, point) { - point = cartesian(point), point[0] -= cosRadius; - cartesianNormalizeInPlace(point); - var radius = acos(-point[1]); - return ((-point[2] < 0 ? -radius : radius) + tau$4 - epsilon$4) % tau$4; +function Radial(curve) { + this._curve = curve; } -var circle$1 = function() { - var center = constant$13([0, 0]), - radius = constant$13(90), - precision = constant$13(6), - ring, - rotate, - stream = {point: point}; - - function point(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= degrees$1, x[1] *= degrees$1; +Radial.prototype = { + areaStart: function() { + this._curve.areaStart(); + }, + areaEnd: function() { + this._curve.areaEnd(); + }, + lineStart: function() { + this._curve.lineStart(); + }, + lineEnd: function() { + this._curve.lineEnd(); + }, + point: function(a, r) { + this._curve.point(r * Math.sin(a), r * -Math.cos(a)); } +}; - function circle() { - var c = center.apply(this, arguments), - r = radius.apply(this, arguments) * radians, - p = precision.apply(this, arguments) * radians; - ring = []; - rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; - circleStream(stream, r, p, 1); - c = {type: "Polygon", coordinates: [ring]}; - ring = rotate = null; - return c; +function curveRadial(curve) { + + function radial(context) { + return new Radial(curve(context)); } - circle.center = function(_) { - return arguments.length ? (center = typeof _ === "function" ? _ : constant$13([+_[0], +_[1]]), circle) : center; - }; + radial._curve = curve; - circle.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant$13(+_), circle) : radius; - }; + return radial; +} - circle.precision = function(_) { - return arguments.length ? (precision = typeof _ === "function" ? _ : constant$13(+_), circle) : precision; +function radialLine(l) { + var c = l.curve; + + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + + l.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; }; - return circle; + return l; +} + +var radialLine$1 = function() { + return radialLine(line().curve(curveRadialLinear)); }; -var clipBuffer = function() { - var lines = [], - line; - return { - point: function(x, y) { - line.push([x, y]); - }, - lineStart: function() { - lines.push(line = []); - }, - lineEnd: noop$2, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - }, - result: function() { - var result = lines; - lines = []; - line = null; - return result; - } +var radialArea = function() { + var a = area$2().curve(curveRadialLinear), + c = a.curve, + x0 = a.lineX0, + x1 = a.lineX1, + y0 = a.lineY0, + y1 = a.lineY1; + + a.angle = a.x, delete a.x; + a.startAngle = a.x0, delete a.x0; + a.endAngle = a.x1, delete a.x1; + a.radius = a.y, delete a.y; + a.innerRadius = a.y0, delete a.y0; + a.outerRadius = a.y1, delete a.y1; + a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0; + a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1; + a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0; + a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1; + + a.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; }; + + return a; }; -var clipLine = function(a, b, x0, y0, x1, y1) { - var ax = a[0], - ay = a[1], - bx = b[0], - by = b[1], - t0 = 0, - t1 = 1, - dx = bx - ax, - dy = by - ay, - r; +var circle$2 = { + draw: function(context, size) { + var r = Math.sqrt(size / pi$4); + context.moveTo(r, 0); + context.arc(0, 0, r, 0, tau$4); + } +}; - 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; +var cross$1 = { + draw: function(context, size) { + var r = Math.sqrt(size / 5) / 2; + context.moveTo(-3 * r, -r); + context.lineTo(-r, -r); + context.lineTo(-r, -3 * r); + context.lineTo(r, -3 * r); + context.lineTo(r, -r); + context.lineTo(3 * r, -r); + context.lineTo(3 * r, r); + context.lineTo(r, r); + context.lineTo(r, 3 * r); + context.lineTo(-r, 3 * r); + context.lineTo(-r, r); + context.lineTo(-3 * r, r); + context.closePath(); } +}; - 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; +var tan30 = Math.sqrt(1 / 3); +var tan30_2 = tan30 * 2; + +var diamond = { + draw: function(context, size) { + var y = Math.sqrt(size / tan30_2), + x = y * tan30; + context.moveTo(0, -y); + context.lineTo(x, 0); + context.lineTo(0, y); + context.lineTo(-x, 0); + context.closePath(); } +}; - 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; +var ka = 0.89081309152928522810; +var kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10); +var kx = Math.sin(tau$4 / 10) * kr; +var ky = -Math.cos(tau$4 / 10) * kr; + +var star = { + draw: function(context, size) { + var r = Math.sqrt(size * ka), + x = kx * r, + y = ky * r; + context.moveTo(0, -r); + context.lineTo(x, y); + for (var i = 1; i < 5; ++i) { + var a = tau$4 * i / 5, + c = Math.cos(a), + s = Math.sin(a); + context.lineTo(s * r, -c * r); + context.lineTo(c * x - s * y, s * x + c * y); + } + context.closePath(); } +}; - 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; +var square = { + draw: function(context, size) { + var w = Math.sqrt(size), + x = -w / 2; + context.rect(x, x, w, w); } +}; - if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; - if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; - return true; +var sqrt3 = Math.sqrt(3); + +var triangle = { + draw: function(context, size) { + var y = -Math.sqrt(size / (sqrt3 * 3)); + context.moveTo(0, y * 2); + context.lineTo(-sqrt3 * y, -y); + context.lineTo(sqrt3 * y, -y); + context.closePath(); + } }; -var pointEqual = function(a, b) { - return abs(a[0] - b[0]) < epsilon$4 && abs(a[1] - b[1]) < epsilon$4; +var c = -0.5; +var s = Math.sqrt(3) / 2; +var k = 1 / Math.sqrt(12); +var a = (k / 2 + 1) * 3; + +var wye = { + draw: function(context, size) { + var r = Math.sqrt(size / a), + x0 = r / 2, + y0 = r * k, + x1 = x0, + y1 = r * k + r, + x2 = -x1, + y2 = y1; + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + context.lineTo(c * x0 - s * y0, s * x0 + c * y0); + context.lineTo(c * x1 - s * y1, s * x1 + c * y1); + context.lineTo(c * x2 - s * y2, s * x2 + c * y2); + context.lineTo(c * x0 + s * y0, c * y0 - s * x0); + context.lineTo(c * x1 + s * y1, c * y1 - s * x1); + context.lineTo(c * x2 + s * y2, c * y2 - s * x2); + context.closePath(); + } }; -function Intersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; // another intersection - this.e = entry; // is an entry? - this.v = false; // visited - this.n = this.p = null; // next & previous -} +var symbols = [ + circle$2, + cross$1, + diamond, + square, + star, + triangle, + wye +]; -// A generalized polygon clipping algorithm: given a polygon that has been cut -// into its visible line segments, and rejoins the segments by interpolating -// along the clip edge. -var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) { - var subject = [], - clip = [], - i, - n; +var symbol = function() { + var type = constant$10(circle$2), + size = constant$10(64), + context = null; - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n], x; + function symbol() { + var buffer; + if (!context) context = buffer = path(); + type.apply(this, arguments).draw(context, +size.apply(this, arguments)); + if (buffer) return context = null, buffer + "" || null; + } - // If the first and last points of a segment are coincident, then treat as a - // closed ring. TODO if all rings are closed, then the winding order of the - // exterior ring should be checked. - if (pointEqual(p0, p1)) { - stream.lineStart(); - for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); - stream.lineEnd(); - return; - } + symbol.type = function(_) { + return arguments.length ? (type = typeof _ === "function" ? _ : constant$10(_), symbol) : type; + }; - subject.push(x = new Intersection(p0, segment, null, true)); - clip.push(x.o = new Intersection(p0, null, x, false)); - subject.push(x = new Intersection(p1, segment, null, false)); - clip.push(x.o = new Intersection(p1, null, x, true)); - }); + symbol.size = function(_) { + return arguments.length ? (size = typeof _ === "function" ? _ : constant$10(+_), symbol) : size; + }; - if (!subject.length) return; + symbol.context = function(_) { + return arguments.length ? (context = _ == null ? null : _, symbol) : context; + }; - clip.sort(compareIntersection); - link$1(subject); - link$1(clip); + return symbol; +}; - for (i = 0, n = clip.length; i < n; ++i) { - clip[i].e = startInside = !startInside; - } +var noop$2 = function() {}; - var start = subject[0], - points, - point; +function point$2(that, x, y) { + that._context.bezierCurveTo( + (2 * that._x0 + that._x1) / 3, + (2 * that._y0 + that._y1) / 3, + (that._x0 + 2 * that._x1) / 3, + (that._y0 + 2 * that._y1) / 3, + (that._x0 + 4 * that._x1 + x) / 6, + (that._y0 + 4 * that._y1 + y) / 6 + ); +} - while (1) { - // Find first unvisited intersection. - var current = start, - isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - stream.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, stream); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, stream); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - stream.lineEnd(); +function Basis(context) { + this._context = context; +} + +Basis.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 3: point$2(this, this._x1, this._y1); // proceed + case 2: this._context.lineTo(this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed + default: point$2(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; } }; -function link$1(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; -} +var basis$2 = function(context) { + return new Basis(context); +}; -var clipMax = 1e9; -var clipMin = -clipMax; +function BasisClosed(context) { + this._context = context; +} -// TODO Use d3-polygon’s polygonContains here for the ring check? -// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? +BasisClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x2, this._y2); + this._context.closePath(); + break; + } + case 2: { + this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); + this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x2, this._y2); + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x2 = x, this._y2 = y; break; + case 1: this._point = 2; this._x3 = x, this._y3 = y; break; + case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; + default: point$2(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; -function clipExtent(x0, y0, x1, y1) { +var basisClosed$1 = function(context) { + return new BasisClosed(context); +}; - function visible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } +function BasisOpen(context) { + this._context = context; +} - function interpolate(from, to, direction, stream) { - var a = 0, a1 = 0; - if (from == null - || (a = corner(from, direction)) !== (a1 = corner(to, direction)) - || comparePoint(from, to) < 0 ^ direction > 0) { - do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - while ((a = (a + direction + 4) % 4) !== a1); - } else { - stream.point(to[0], to[1]); +BasisOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; + case 3: this._point = 4; // proceed + default: point$2(this, x, y); break; } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; } +}; - function corner(p, direction) { - return abs(p[0] - x0) < epsilon$4 ? direction > 0 ? 0 : 3 - : abs(p[0] - x1) < epsilon$4 ? direction > 0 ? 2 : 1 - : abs(p[1] - y0) < epsilon$4 ? direction > 0 ? 1 : 0 - : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon - } - - function compareIntersection(a, b) { - return comparePoint(a.x, b.x); - } +var basisOpen = function(context) { + return new BasisOpen(context); +}; - function comparePoint(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 Bundle(context, beta) { + this._basis = new Basis(context); + this._beta = beta; +} - return function(stream) { - var activeStream = stream, - bufferStream = clipBuffer(), - segments, - polygon, - ring, - x__, y__, v__, // first point - x_, y_, v_, // previous point - first, - clean; +Bundle.prototype = { + lineStart: function() { + this._x = []; + this._y = []; + this._basis.lineStart(); + }, + lineEnd: function() { + var x = this._x, + y = this._y, + j = x.length - 1; - var clipStream = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: polygonStart, - polygonEnd: polygonEnd - }; + if (j > 0) { + var x0 = x[0], + y0 = y[0], + dx = x[j] - x0, + dy = y[j] - y0, + i = -1, + t; - function point(x, y) { - if (visible(x, y)) activeStream.point(x, y); + while (++i <= j) { + t = i / j; + this._basis.point( + this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), + this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) + ); + } } - function polygonInside() { - var winding = 0; + this._x = this._y = null; + this._basis.lineEnd(); + }, + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } +}; - for (var i = 0, n = polygon.length; i < n; ++i) { - for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { - a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; - if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } - else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } - } - } +var bundle = ((function custom(beta) { - return winding; - } + function bundle(context) { + return beta === 1 ? new Basis(context) : new Bundle(context, beta); + } - // Buffer geometry within a polygon and then clip it en masse. - function polygonStart() { - activeStream = bufferStream, segments = [], polygon = [], clean = true; - } + bundle.beta = function(beta) { + return custom(+beta); + }; - function polygonEnd() { - var startInside = polygonInside(), - cleanInside = clean && startInside, - visible = (segments = merge(segments)).length; - if (cleanInside || visible) { - stream.polygonStart(); - if (cleanInside) { - stream.lineStart(); - interpolate(null, null, 1, stream); - stream.lineEnd(); - } - if (visible) { - clipPolygon(segments, compareIntersection, startInside, interpolate, stream); - } - stream.polygonEnd(); - } - activeStream = stream, segments = polygon = ring = null; - } + return bundle; +}))(0.85); - function lineStart() { - clipStream.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } +function point$3(that, x, y) { + that._context.bezierCurveTo( + that._x1 + that._k * (that._x2 - that._x0), + that._y1 + that._k * (that._y2 - that._y0), + that._x2 + that._k * (that._x1 - x), + that._y2 + that._k * (that._y1 - y), + that._x2, + that._y2 + ); +} - // TODO rather than special-case polygons, simply handle them separately. - // Ideally, coincident intersection points should be jittered to avoid - // clipping issues. - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferStream.rejoin(); - segments.push(bufferStream.result()); - } - clipStream.point = point; - if (v_) activeStream.lineEnd(); - } +function Cardinal(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} - function linePoint(x, y) { - var v = visible(x, y); - if (polygon) ring.push([x, y]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - activeStream.lineStart(); - activeStream.point(x, y); - } - } else { - if (v && v_) activeStream.point(x, y); - else { - var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], - b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; - if (clipLine(a, b, x0, y0, x1, y1)) { - if (!v_) { - activeStream.lineStart(); - activeStream.point(a[0], a[1]); - } - activeStream.point(b[0], b[1]); - if (!v) activeStream.lineEnd(); - clean = false; - } else if (v) { - activeStream.lineStart(); - activeStream.point(x, y); - clean = false; - } - } - } - x_ = x, y_ = y, v_ = v; +Cardinal.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: point$3(this, this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; this._x1 = x, this._y1 = y; break; + case 2: this._point = 3; // proceed + default: point$3(this, x, y); break; } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; - return clipStream; - }; -} +var cardinal = ((function custom(tension) { -var extent$1 = function() { - var x0 = 0, - y0 = 0, - x1 = 960, - y1 = 500, - cache, - cacheStream, - clip; + function cardinal(context) { + return new Cardinal(context, tension); + } - return clip = { - stream: function(stream) { - return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream); - }, - extent: function(_) { - return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; - } + cardinal.tension = function(tension) { + return custom(+tension); }; -}; -var lengthSum = adder(); -var lambda0$2; -var sinPhi0$1; -var cosPhi0$1; + return cardinal; +}))(0); -var lengthStream = { - sphere: noop$2, - point: noop$2, - lineStart: lengthLineStart, - lineEnd: noop$2, - polygonStart: noop$2, - polygonEnd: noop$2 +function CardinalClosed(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$3(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } }; -function lengthLineStart() { - lengthStream.point = lengthPointFirst; - lengthStream.lineEnd = lengthLineEnd; -} +var cardinalClosed = ((function custom(tension) { -function lengthLineEnd() { - lengthStream.point = lengthStream.lineEnd = noop$2; -} + function cardinal(context) { + return new CardinalClosed(context, tension); + } -function lengthPointFirst(lambda, phi) { - lambda *= radians, phi *= radians; - lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi); - lengthStream.point = lengthPoint; -} + cardinal.tension = function(tension) { + return custom(+tension); + }; -function lengthPoint(lambda, phi) { - lambda *= radians, phi *= radians; - var sinPhi = sin$1(phi), - cosPhi = cos$1(phi), - delta = abs(lambda - lambda0$2), - cosDelta = cos$1(delta), - sinDelta = sin$1(delta), - x = cosPhi * sinDelta, - y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, - z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; - lengthSum.add(atan2(sqrt$1(x * x + y * y), z)); - lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; + return cardinal; +}))(0); + +function CardinalOpen(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; } -var length$2 = function(object) { - lengthSum.reset(); - geoStream(object, lengthStream); - return +lengthSum; +CardinalOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$3(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } }; -var coordinates = [null, null]; -var object$1 = {type: "LineString", coordinates: coordinates}; +var cardinalOpen = ((function custom(tension) { -var distance = function(a, b) { - coordinates[0] = a; - coordinates[1] = b; - return length$2(object$1); -}; + function cardinal(context) { + return new CardinalOpen(context, tension); + } -function graticuleX(y0, y1, dy) { - var y = range(y0, y1 - epsilon$4, dy).concat(y1); - return function(x) { return y.map(function(y) { return [x, y]; }); }; -} + cardinal.tension = function(tension) { + return custom(+tension); + }; -function graticuleY(x0, x1, dx) { - var x = range(x0, x1 - epsilon$4, dx).concat(x1); - return function(y) { return x.map(function(x) { return [x, y]; }); }; -} + return cardinal; +}))(0); -function graticule() { - 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 point$4(that, x, y) { + var x1 = that._x1, + y1 = that._y1, + x2 = that._x2, + y2 = that._y2; - function graticule() { - return {type: "MultiLineString", coordinates: lines()}; + if (that._l01_a > epsilon$3) { + var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, + n = 3 * that._l01_a * (that._l01_a + that._l12_a); + x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; + y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; } - function lines() { - return range(ceil(X0 / DX) * DX, X1, DX).map(X) - .concat(range(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) - .concat(range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$4; }).map(x)) - .concat(range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$4; }).map(y)); + if (that._l23_a > epsilon$3) { + var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, + m = 3 * that._l23_a * (that._l23_a + that._l12_a); + x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; + y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; } - 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)) - ] - }; - }; + that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); +} - graticule.extent = function(_) { - if (!arguments.length) return graticule.extentMinor(); - return graticule.extentMajor(_).extentMinor(_); - }; +function CatmullRom(context, alpha) { + this._context = context; + this._alpha = alpha; +} - graticule.extentMajor = 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); - }; +CatmullRom.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: this.point(this._x2, this._y2); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; - graticule.extentMinor = 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); - }; + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } - graticule.step = function(_) { - if (!arguments.length) return graticule.stepMinor(); - return graticule.stepMajor(_).stepMinor(_); - }; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; // proceed + default: point$4(this, x, y); break; + } - graticule.stepMajor = function(_) { - if (!arguments.length) return [DX, DY]; - DX = +_[0], DY = +_[1]; - return graticule; - }; + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; - graticule.stepMinor = function(_) { - if (!arguments.length) return [dx, dy]; - dx = +_[0], dy = +_[1]; - return graticule; - }; +var catmullRom = ((function custom(alpha) { - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = graticuleX(y0, y1, 90); - y = graticuleY(x0, x1, precision); - X = graticuleX(Y0, Y1, 90); - Y = graticuleY(X0, X1, precision); - return graticule; + function catmullRom(context) { + return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); }; - return graticule - .extentMajor([[-180, -90 + epsilon$4], [180, 90 - epsilon$4]]) - .extentMinor([[-180, -80 - epsilon$4], [180, 80 + epsilon$4]]); -} + return catmullRom; +}))(0.5); -function graticule10() { - return graticule()(); +function CatmullRomClosed(context, alpha) { + this._context = context; + this._alpha = alpha; } -var interpolate$2 = function(a, b) { - var x0 = a[0] * radians, - y0 = a[1] * radians, - x1 = b[0] * radians, - y1 = b[1] * radians, - cy0 = cos$1(y0), - sy0 = sin$1(y0), - cy1 = cos$1(y1), - sy1 = sin$1(y1), - kx0 = cy0 * cos$1(x0), - ky0 = cy0 * sin$1(x0), - kx1 = cy1 * cos$1(x1), - ky1 = cy1 * sin$1(x1), - d = 2 * asin$1(sqrt$1(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), - k = sin$1(d); - - var interpolate = d ? function(t) { - var B = sin$1(t *= d) / k, - A = sin$1(d - t) / k, - x = A * kx0 + B * kx1, - y = A * ky0 + B * ky1, - z = A * sy0 + B * sy1; - return [ - atan2(y, x) * degrees$1, - atan2(z, sqrt$1(x * x + y * y)) * degrees$1 - ]; - } : function() { - return [x0 * degrees$1, y0 * degrees$1]; - }; +CatmullRomClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; - interpolate.distance = d; + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } - return interpolate; -}; + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$4(this, x, y); break; + } -var identity$7 = function(x) { - return x; + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } }; -var areaSum$1 = adder(); -var areaRingSum$1 = adder(); -var x00; -var y00; -var x0$1; -var y0$1; +var catmullRomClosed = ((function custom(alpha) { -var areaStream$1 = { - point: noop$2, - lineStart: noop$2, - lineEnd: noop$2, - polygonStart: function() { - areaStream$1.lineStart = areaRingStart$1; - areaStream$1.lineEnd = areaRingEnd$1; - }, - polygonEnd: function() { - areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$2; - areaSum$1.add(abs(areaRingSum$1)); - areaRingSum$1.reset(); - }, - result: function() { - var area = areaSum$1 / 2; - areaSum$1.reset(); - return area; + function catmullRom(context) { + return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); } -}; -function areaRingStart$1() { - areaStream$1.point = areaPointFirst$1; -} + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; -function areaPointFirst$1(x, y) { - areaStream$1.point = areaPoint$1; - x00 = x0$1 = x, y00 = y0$1 = y; -} + return catmullRom; +}))(0.5); -function areaPoint$1(x, y) { - areaRingSum$1.add(y0$1 * x - x0$1 * y); - x0$1 = x, y0$1 = y; +function CatmullRomOpen(context, alpha) { + this._context = context; + this._alpha = alpha; } -function areaRingEnd$1() { - areaPoint$1(x00, y00); -} +CatmullRomOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; -var x0$2 = Infinity; -var y0$2 = x0$2; -var x1 = -x0$2; -var y1 = x1; + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } -var boundsStream$1 = { - point: boundsPoint$1, - lineStart: noop$2, - lineEnd: noop$2, - polygonStart: noop$2, - polygonEnd: noop$2, - result: function() { - var bounds = [[x0$2, y0$2], [x1, y1]]; - x1 = y1 = -(y0$2 = x0$2 = Infinity); - return bounds; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$4(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; } }; -function boundsPoint$1(x, y) { - if (x < x0$2) x0$2 = x; - if (x > x1) x1 = x; - if (y < y0$2) y0$2 = y; - if (y > y1) y1 = y; -} +var catmullRomOpen = ((function custom(alpha) { -// TODO Enforce positive area for exterior, negative area for interior? + function catmullRom(context) { + return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); + } -var X0$1 = 0; -var Y0$1 = 0; -var Z0$1 = 0; -var X1$1 = 0; -var Y1$1 = 0; -var Z1$1 = 0; -var X2$1 = 0; -var Y2$1 = 0; -var Z2$1 = 0; -var x00$1; -var y00$1; -var x0$3; -var y0$3; + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; -var centroidStream$1 = { - point: centroidPoint$1, - lineStart: centroidLineStart$1, - lineEnd: centroidLineEnd$1, - polygonStart: function() { - centroidStream$1.lineStart = centroidRingStart$1; - centroidStream$1.lineEnd = centroidRingEnd$1; - }, - polygonEnd: function() { - centroidStream$1.point = centroidPoint$1; - centroidStream$1.lineStart = centroidLineStart$1; - centroidStream$1.lineEnd = centroidLineEnd$1; - }, - result: function() { - var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] - : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] - : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] - : [NaN, NaN]; - X0$1 = Y0$1 = Z0$1 = - X1$1 = Y1$1 = Z1$1 = - X2$1 = Y2$1 = Z2$1 = 0; - return centroid; + return catmullRom; +}))(0.5); + +function LinearClosed(context) { + this._context = context; +} + +LinearClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._point) this._context.closePath(); + }, + point: function(x, y) { + x = +x, y = +y; + if (this._point) this._context.lineTo(x, y); + else this._point = 1, this._context.moveTo(x, y); } }; -function centroidPoint$1(x, y) { - X0$1 += x; - Y0$1 += y; - ++Z0$1; -} +var linearClosed = function(context) { + return new LinearClosed(context); +}; -function centroidLineStart$1() { - centroidStream$1.point = centroidPointFirstLine; +function sign$1(x) { + return x < 0 ? -1 : 1; } -function centroidPointFirstLine(x, y) { - centroidStream$1.point = centroidPointLine; - centroidPoint$1(x0$3 = x, y0$3 = y); +// Calculate the slopes of the tangents (Hermite-type interpolation) based on +// the following paper: Steffen, M. 1990. A Simple Method for Monotonic +// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. +// NOV(II), P. 443, 1990. +function slope3(that, x2, y2) { + var h0 = that._x1 - that._x0, + h1 = x2 - that._x1, + s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), + s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), + p = (s0 * h1 + s1 * h0) / (h0 + h1); + return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; } -function centroidPointLine(x, y) { - var dx = x - x0$3, dy = y - y0$3, z = sqrt$1(dx * dx + dy * dy); - X1$1 += z * (x0$3 + x) / 2; - Y1$1 += z * (y0$3 + y) / 2; - Z1$1 += z; - centroidPoint$1(x0$3 = x, y0$3 = y); +// Calculate a one-sided slope. +function slope2(that, t) { + var h = that._x1 - that._x0; + return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; } -function centroidLineEnd$1() { - centroidStream$1.point = centroidPoint$1; +// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations +// "you can express cubic Hermite interpolation in terms of cubic Bézier curves +// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". +function point$5(that, t0, t1) { + var x0 = that._x0, + y0 = that._y0, + x1 = that._x1, + y1 = that._y1, + dx = (x1 - x0) / 3; + that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); } -function centroidRingStart$1() { - centroidStream$1.point = centroidPointFirstRing; +function MonotoneX(context) { + this._context = context; } -function centroidRingEnd$1() { - centroidPointRing(x00$1, y00$1); +MonotoneX.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = + this._t0 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x1, this._y1); break; + case 3: point$5(this, this._t0, slope2(this, this._t0)); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + var t1 = NaN; + + x = +x, y = +y; + if (x === this._x1 && y === this._y1) return; // Ignore coincident points. + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break; + default: point$5(this, this._t0, t1 = slope3(this, x, y)); break; + } + + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + this._t0 = t1; + } +}; + +function MonotoneY(context) { + this._context = new ReflectContext(context); } -function centroidPointFirstRing(x, y) { - centroidStream$1.point = centroidPointRing; - centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); +(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { + MonotoneX.prototype.point.call(this, y, x); +}; + +function ReflectContext(context) { + this._context = context; } -function centroidPointRing(x, y) { - var dx = x - x0$3, - dy = y - y0$3, - z = sqrt$1(dx * dx + dy * dy); +ReflectContext.prototype = { + moveTo: function(x, y) { this._context.moveTo(y, x); }, + closePath: function() { this._context.closePath(); }, + lineTo: function(x, y) { this._context.lineTo(y, x); }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } +}; - X1$1 += z * (x0$3 + x) / 2; - Y1$1 += z * (y0$3 + y) / 2; - Z1$1 += z; +function monotoneX(context) { + return new MonotoneX(context); +} - z = y0$3 * x - x0$3 * y; - X2$1 += z * (x0$3 + x); - Y2$1 += z * (y0$3 + y); - Z2$1 += z * 3; - centroidPoint$1(x0$3 = x, y0$3 = y); +function monotoneY(context) { + return new MonotoneY(context); } -function PathContext(context) { +function Natural(context) { this._context = context; } -PathContext.prototype = { - _radius: 4.5, - pointRadius: function(_) { - return this._radius = _, this; - }, - polygonStart: function() { +Natural.prototype = { + areaStart: function() { this._line = 0; }, - polygonEnd: function() { + areaEnd: function() { this._line = NaN; }, lineStart: function() { - this._point = 0; + this._x = []; + this._y = []; }, lineEnd: function() { - if (this._line === 0) this._context.closePath(); - this._point = NaN; - }, - point: function(x, y) { - switch (this._point) { - case 0: { - this._context.moveTo(x, y); - this._point = 1; - break; - } - case 1: { - this._context.lineTo(x, y); - break; - } - default: { - this._context.moveTo(x + this._radius, y); - this._context.arc(x, y, this._radius, 0, tau$4); - break; + var x = this._x, + y = this._y, + n = x.length; + + if (n) { + this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); + if (n === 2) { + this._context.lineTo(x[1], y[1]); + } else { + var px = controlPoints(x), + py = controlPoints(y); + for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { + this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); + } } } + + if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); + this._line = 1 - this._line; + this._x = this._y = null; }, - result: noop$2 + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } }; -function PathString() { - this._string = []; +// See https://www.particleincell.com/2012/bezier-splines/ for derivation. +function controlPoints(x) { + var i, + n = x.length - 1, + m, + a = new Array(n), + b = new Array(n), + r = new Array(n); + a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; + for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; + a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; + for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; + a[n - 1] = r[n - 1] / b[n - 1]; + for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; + b[n - 1] = (x[n] + a[n - 1]) / 2; + for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; + return [a, b]; } -PathString.prototype = { - _circle: circle$2(4.5), - pointRadius: function(_) { - return this._circle = circle$2(_), this; - }, - polygonStart: function() { +var natural = function(context) { + return new Natural(context); +}; + +function Step(context, t) { + this._context = context; + this._t = t; +} + +Step.prototype = { + areaStart: function() { this._line = 0; }, - polygonEnd: function() { + areaEnd: function() { this._line = NaN; }, lineStart: function() { + this._x = this._y = NaN; this._point = 0; }, lineEnd: function() { - if (this._line === 0) this._string.push("Z"); - this._point = NaN; + if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; }, point: function(x, y) { + x = +x, y = +y; switch (this._point) { - case 0: { - this._string.push("M", x, ",", y); - this._point = 1; - break; - } - case 1: { - this._string.push("L", x, ",", y); - break; - } + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed default: { - this._string.push("M", x, ",", y, this._circle); - break; - } - } - }, - result: function() { - if (this._string.length) { - var result = this._string.join(""); - this._string = []; - return result; + if (this._t <= 0) { + this._context.lineTo(this._x, y); + this._context.lineTo(x, y); + } else { + var x1 = this._x * (1 - this._t) + x * this._t; + this._context.lineTo(x1, this._y); + this._context.lineTo(x1, y); + } + break; + } } + this._x = x, this._y = y; } }; -function circle$2(radius) { - return "m0," + radius - + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius - + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius - + "z"; +var step = function(context) { + return new Step(context, 0.5); +}; + +function stepBefore(context) { + return new Step(context, 0); } -var index$3 = function(projection, context) { - var pointRadius = 4.5, - projectionStream, - contextStream; +function stepAfter(context) { + return new Step(context, 1); +} - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - geoStream(object, projectionStream(contextStream)); +var slice$5 = Array.prototype.slice; + +var none$1 = function(series, order) { + if (!((n = series.length) > 1)) return; + for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { + s0 = s1, s1 = series[order[i]]; + for (var j = 0; j < m; ++j) { + s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; } - return contextStream.result(); } +}; - path.area = function(object) { - geoStream(object, projectionStream(areaStream$1)); - return areaStream$1.result(); - }; +var none$2 = function(series) { + var n = series.length, o = new Array(n); + while (--n >= 0) o[n] = n; + return o; +}; - path.bounds = function(object) { - geoStream(object, projectionStream(boundsStream$1)); - return boundsStream$1.result(); - }; +function stackValue(d, key) { + return d[key]; +} - path.centroid = function(object) { - geoStream(object, projectionStream(centroidStream$1)); - return centroidStream$1.result(); +var stack = function() { + var keys = constant$10([]), + order = none$2, + offset = none$1, + value = stackValue; + + function stack(data) { + var kz = keys.apply(this, arguments), + i, + m = data.length, + n = kz.length, + sz = new Array(n), + oz; + + for (i = 0; i < n; ++i) { + for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { + si[j] = sij = [0, +value(data[j], ki, j, data)]; + sij.data = data[j]; + } + si.key = ki; + } + + for (i = 0, oz = order(sz); i < n; ++i) { + sz[oz[i]].index = i; + } + + offset(sz, oz); + return sz; + } + + stack.keys = function(_) { + return arguments.length ? (keys = typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : keys; }; - path.projection = function(_) { - return arguments.length ? (projectionStream = (projection = _) == null ? identity$7 : _.stream, path) : projection; + stack.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), stack) : value; }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new PathString : new PathContext(_); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return path; + stack.order = function(_) { + return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : order; }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; + stack.offset = function(_) { + return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset; }; - return path.projection(projection).context(context); + return stack; +}; + +var expand = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { + for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; + if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; + } + none$1(series, order); }; -var sum$2 = adder(); +var silhouette = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { + for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; + s0[j][1] += s0[j][0] = -y / 2; + } + none$1(series, order); +}; -var polygonContains = function(polygon, point) { - var lambda = point[0], - phi = point[1], - normal = [sin$1(lambda), -cos$1(lambda), 0], - angle = 0, - winding = 0; +var wiggle = function(series, order) { + if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; + for (var y = 0, j = 1, s0, m, n; j < m; ++j) { + for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { + var si = series[order[i]], + sij0 = si[j][1] || 0, + sij1 = si[j - 1][1] || 0, + s3 = (sij0 - sij1) / 2; + for (var k = 0; k < i; ++k) { + var sk = series[order[k]], + skj0 = sk[j][1] || 0, + skj1 = sk[j - 1][1] || 0; + s3 += skj0 - skj1; + } + s1 += sij0, s2 += s3 * sij0; + } + s0[j - 1][1] += s0[j - 1][0] = y; + if (s1) y -= s2 / s1; + } + s0[j - 1][1] += s0[j - 1][0] = y; + none$1(series, order); +}; - sum$2.reset(); +var ascending$2 = function(series) { + var sums = series.map(sum$2); + return none$2(series).sort(function(a, b) { return sums[a] - sums[b]; }); +}; - for (var i = 0, n = polygon.length; i < n; ++i) { - if (!(m = (ring = polygon[i]).length)) continue; - var ring, - m, - point0 = ring[m - 1], - lambda0 = point0[0], - phi0 = point0[1] / 2 + quarterPi, - sinPhi0 = sin$1(phi0), - cosPhi0 = cos$1(phi0); +function sum$2(series) { + var s = 0, i = -1, n = series.length, v; + while (++i < n) if (v = +series[i][1]) s += v; + return s; +} - for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { - var point1 = ring[j], - lambda1 = point1[0], - phi1 = point1[1] / 2 + quarterPi, - sinPhi1 = sin$1(phi1), - cosPhi1 = cos$1(phi1), - delta = lambda1 - lambda0, - sign$$1 = delta >= 0 ? 1 : -1, - absDelta = sign$$1 * delta, - antimeridian = absDelta > pi$4, - k = sinPhi0 * sinPhi1; +var descending$2 = function(series) { + return ascending$2(series).reverse(); +}; - sum$2.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta))); - angle += antimeridian ? delta + sign$$1 * tau$4 : delta; +var insideOut = function(series) { + var n = series.length, + i, + j, + sums = series.map(sum$2), + order = none$2(series).sort(function(a, b) { return sums[b] - sums[a]; }), + top = 0, + bottom = 0, + tops = [], + bottoms = []; - // Are the longitudes either side of the point’s meridian (lambda), - // and are the latitudes smaller than the parallel (phi)? - if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { - var arc = cartesianCross(cartesian(point0), cartesian(point1)); - cartesianNormalizeInPlace(arc); - var intersection = cartesianCross(normal, arc); - cartesianNormalizeInPlace(intersection); - var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin$1(intersection[2]); - if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { - winding += antimeridian ^ delta >= 0 ? 1 : -1; - } - } + for (i = 0; i < n; ++i) { + j = order[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); } } - // First, determine whether the South pole is inside or outside: - // - // It is inside if: - // * the polygon winds around it in a clockwise direction. - // * the polygon does not (cumulatively) wind around it, but has a negative - // (counter-clockwise) area. - // - // Second, count the (signed) number of times a segment crosses a lambda - // from the point to the South pole. If it is zero, then the point is the - // same side as the South pole. + return bottoms.reverse().concat(tops); +}; - return (angle < -epsilon$4 || angle < epsilon$4 && sum$2 < -epsilon$4) ^ (winding & 1); +var reverse = function(series) { + return none$2(series).reverse(); }; -var clip = function(pointVisible, clipLine, interpolate, start) { - return function(rotate, sink) { - var line = clipLine(sink), - rotatedStart = rotate.invert(start[0], start[1]), - ringBuffer = clipBuffer(), - ringSink = clipLine(ringBuffer), - polygonStarted = false, - polygon, - segments, - ring; +var constant$11 = function(x) { + return function() { + return x; + }; +}; + +function x$4(d) { + return d[0]; +} + +function y$4(d) { + return d[1]; +} + +function RedBlackTree() { + this._ = null; // root node +} + +function RedBlackNode(node) { + node.U = // parent node + node.C = // color - true for red, false for black + node.L = // left node + node.R = // right node + node.P = // previous node + node.N = null; // next node +} + +RedBlackTree.prototype = { + constructor: RedBlackTree, + + 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 = RedBlackFirst(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; - 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 = merge(segments); - var startInside = polygonContains(polygon, rotatedStart); - if (segments.length) { - if (!polygonStarted) sink.polygonStart(), polygonStarted = true; - clipPolygon(segments, compareIntersection, startInside, interpolate, sink); - } else if (startInside) { - if (!polygonStarted) sink.polygonStart(), polygonStarted = true; - sink.lineStart(); - interpolate(null, null, 1, sink); - sink.lineEnd(); + 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) { + RedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + RedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateLeft(this, grandpa); } - if (polygonStarted) sink.polygonEnd(), polygonStarted = false; - segments = polygon = null; - }, - sphere: function() { - sink.polygonStart(); - sink.lineStart(); - interpolate(null, null, 1, sink); - sink.lineEnd(); - sink.polygonEnd(); } - }; - - function point(lambda, phi) { - var point = rotate(lambda, phi); - if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi); + parent = after.U; } + this._.C = false; + }, - function pointLine(lambda, phi) { - var point = rotate(lambda, phi); - line.point(point[0], point[1]); - } + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } + var parent = node.U, + sibling, + left = node.L, + right = node.R, + next, + red; - function lineEnd() { - clip.point = point; - line.lineEnd(); - } + if (!left) next = right; + else if (!right) next = left; + else next = RedBlackFirst(right); - function pointRing(lambda, phi) { - ring.push([lambda, phi]); - var point = rotate(lambda, phi); - ringSink.point(point[0], point[1]); + if (parent) { + if (parent.L === node) parent.L = next; + else parent.R = next; + } else { + this._ = next; } - function ringStart() { - ringSink.lineStart(); - ring = []; + 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 { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; } - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringSink.lineEnd(); + if (node) node.U = parent; + if (red) return; + if (node && node.C) { node.C = false; return; } - var clean = ringSink.clean(), - ringSegments = ringBuffer.result(), - i, n = ringSegments.length, m, - segment, - point; + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateLeft(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; + RedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + RedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateRight(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; + RedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + RedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); - ring.pop(); - polygon.push(ring); - ring = null; + if (node) node.C = false; + } +}; - if (!n) return; +function RedBlackRotateLeft(tree, node) { + var p = node, + q = node.R, + parent = p.U; - // No intersections. - if (clean & 1) { - segment = ringSegments[0]; - if ((m = segment.length - 1) > 0) { - if (!polygonStarted) sink.polygonStart(), polygonStarted = true; - sink.lineStart(); - for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); - sink.lineEnd(); - } - return; - } + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } - // Rejoin connected segments. - // TODO reuse ringBuffer.rejoin()? - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; +} - segments.push(ringSegments.filter(validSegment)); - } +function RedBlackRotateRight(tree, node) { + var p = node, + q = node.L, + parent = p.U; - return clip; - }; -}; + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } -function validSegment(segment) { - return segment.length > 1; + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; } -// Intersections are sorted along the clip edge. For both antimeridian cutting -// and circle clipping, the same comparison is used. -function compareIntersection(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfPi$3 - epsilon$4 : halfPi$3 - a[1]) - - ((b = b.x)[0] < 0 ? b[1] - halfPi$3 - epsilon$4 : halfPi$3 - b[1]); +function RedBlackFirst(node) { + while (node.L) node = node.L; + return node; } -var clipAntimeridian = clip( - function() { return true; }, - clipAntimeridianLine, - clipAntimeridianInterpolate, - [-pi$4, -halfPi$3] -); - -// Takes a line and cuts into visible segments. Return values: 0 - there were -// intersections or the line was empty; 1 - no intersections; 2 - there were -// intersections, and the first and last segments should be rejoined. -function clipAntimeridianLine(stream) { - var lambda0 = NaN, - phi0 = NaN, - sign0 = NaN, - clean; // no intersections - - return { - lineStart: function() { - stream.lineStart(); - clean = 1; - }, - point: function(lambda1, phi1) { - var sign1 = lambda1 > 0 ? pi$4 : -pi$4, - delta = abs(lambda1 - lambda0); - if (abs(delta - pi$4) < epsilon$4) { // line crosses a pole - stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$3 : -halfPi$3); - stream.point(sign0, phi0); - stream.lineEnd(); - stream.lineStart(); - stream.point(sign1, phi0); - stream.point(lambda1, phi0); - clean = 0; - } else if (sign0 !== sign1 && delta >= pi$4) { // line crosses antimeridian - if (abs(lambda0 - sign0) < epsilon$4) lambda0 -= sign0 * epsilon$4; // handle degeneracies - if (abs(lambda1 - sign1) < epsilon$4) lambda1 -= sign1 * epsilon$4; - phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); - stream.point(sign0, phi0); - stream.lineEnd(); - stream.lineStart(); - stream.point(sign1, phi0); - clean = 0; - } - stream.point(lambda0 = lambda1, phi0 = phi1); - sign0 = sign1; - }, - lineEnd: function() { - stream.lineEnd(); - lambda0 = phi0 = NaN; - }, - clean: function() { - return 2 - clean; // if intersections, rejoin first and last segments - } - }; +function createEdge(left, right, v0, v1) { + var edge = [null, null], + index = edges.push(edge) - 1; + edge.left = left; + edge.right = right; + if (v0) setEdgeEnd(edge, left, right, v0); + if (v1) setEdgeEnd(edge, right, left, v1); + cells[left.index].halfedges.push(index); + cells[right.index].halfedges.push(index); + return edge; } -function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { - var cosPhi0, - cosPhi1, - sinLambda0Lambda1 = sin$1(lambda0 - lambda1); - return abs(sinLambda0Lambda1) > epsilon$4 - ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1) - - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0)) - / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) - : (phi0 + phi1) / 2; +function createBorderEdge(left, v0, v1) { + var edge = [v0, v1]; + edge.left = left; + return edge; } -function clipAntimeridianInterpolate(from, to, direction, stream) { - var phi; - if (from == null) { - phi = direction * halfPi$3; - stream.point(-pi$4, phi); - stream.point(0, phi); - stream.point(pi$4, phi); - stream.point(pi$4, 0); - stream.point(pi$4, -phi); - stream.point(0, -phi); - stream.point(-pi$4, -phi); - stream.point(-pi$4, 0); - stream.point(-pi$4, phi); - } else if (abs(from[0] - to[0]) > epsilon$4) { - var lambda = from[0] < to[0] ? pi$4 : -pi$4; - phi = direction * lambda / 2; - stream.point(-lambda, phi); - stream.point(0, phi); - stream.point(lambda, phi); +function setEdgeEnd(edge, left, right, vertex) { + if (!edge[0] && !edge[1]) { + edge[0] = vertex; + edge.left = left; + edge.right = right; + } else if (edge.left === right) { + edge[1] = vertex; } else { - stream.point(to[0], to[1]); + edge[0] = vertex; } } -var clipCircle = function(radius, delta) { - var cr = cos$1(radius), - smallRadius = cr > 0, - notHemisphere = abs(cr) > epsilon$4; // TODO optimise for this common case +// Liang–Barsky line clipping. +function clipEdge(edge, x0, y0, x1, y1) { + var a = edge[0], + b = edge[1], + ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; - function interpolate(from, to, direction, stream) { - circleStream(stream, radius, delta, direction, from, to); + 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; } - function visible(lambda, phi) { - return cos$1(lambda) * cos$1(phi) > cr; + 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; } - // Takes a line and cuts into visible segments. Return values used for polygon - // clipping: 0 - there were intersections or the line was empty; 1 - no - // intersections 2 - there were intersections, and the first and last segments - // should be rejoined. - function clipLine(stream) { - var point0, // previous point - c0, // code for previous point - v0, // visibility of previous point - v00, // visibility of first point - clean; // no intersections - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(lambda, phi) { - var point1 = [lambda, phi], - point2, - v = visible(lambda, phi), - c = smallRadius - ? v ? 0 : code(lambda, phi) - : v ? code(lambda + (lambda < 0 ? pi$4 : -pi$4), phi) : 0; - if (!point0 && (v00 = v0 = v)) stream.lineStart(); - // Handle degeneracies. - // TODO ignore if not clipping polygons. - if (v !== v0) { - point2 = intersect(point0, point1); - if (pointEqual(point0, point2) || pointEqual(point1, point2)) { - point1[0] += epsilon$4; - point1[1] += epsilon$4; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - // outside going in - stream.lineStart(); - point2 = intersect(point1, point0); - stream.point(point2[0], point2[1]); - } else { - // inside going out - point2 = intersect(point0, point1); - stream.point(point2[0], point2[1]); - stream.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - // If the codes for two points are different, or are both zero, - // and there this segment intersects with the small circle. - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - stream.lineStart(); - stream.point(t[0][0], t[0][1]); - stream.point(t[1][0], t[1][1]); - stream.lineEnd(); - } else { - stream.point(t[1][0], t[1][1]); - stream.lineEnd(); - stream.lineStart(); - stream.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !pointEqual(point0, point1))) { - stream.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) stream.lineEnd(); - point0 = null; - }, - // Rejoin first and last segments if there were intersections and the first - // and last points were visible. - clean: function() { - return clean | ((v00 && v0) << 1); + 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) && !(t1 < 1)) return true; // TODO Better check? + + if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy]; + if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy]; + return true; +} + +function connectEdge(edge, x0, y0, x1, y1) { + var v1 = edge[1]; + if (v1) return true; + + var v0 = edge[0], + left = edge.left, + right = edge.right, + lx = left[0], + ly = left[1], + rx = right[0], + ry = right[1], + fx = (lx + rx) / 2, + fy = (ly + ry) / 2, + fm, + fb; + + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!v0) v0 = [fx, y0]; + else if (v0[1] >= y1) return; + v1 = [fx, y1]; + } else { + if (!v0) v0 = [fx, y1]; + else if (v0[1] < y0) return; + v1 = [fx, y0]; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!v0) v0 = [(y0 - fb) / fm, y0]; + else if (v0[1] >= y1) return; + v1 = [(y1 - fb) / fm, y1]; + } else { + if (!v0) v0 = [(y1 - fb) / fm, y1]; + else if (v0[1] < y0) return; + v1 = [(y0 - fb) / fm, y0]; } - }; + } else { + if (ly < ry) { + if (!v0) v0 = [x0, fm * x0 + fb]; + else if (v0[0] >= x1) return; + v1 = [x1, fm * x1 + fb]; + } else { + if (!v0) v0 = [x1, fm * x1 + fb]; + else if (v0[0] < x0) return; + v1 = [x0, fm * x0 + fb]; + } + } } - // Intersects the great circle between a and b with the clip circle. - function intersect(a, b, two) { - var pa = cartesian(a), - pb = cartesian(b); + edge[0] = v0; + edge[1] = v1; + return true; +} - // We have two planes, n1.p = d1 and n2.p = d2. - // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). - var n1 = [1, 0, 0], // normal - n2 = cartesianCross(pa, pb), - n2n2 = cartesianDot(n2, n2), - n1n2 = n2[0], // cartesianDot(n1, n2), - determinant = n2n2 - n1n2 * n1n2; +function clipEdges(x0, y0, x1, y1) { + var i = edges.length, + edge; - // Two polar points. - if (!determinant) return !two && a; + while (i--) { + if (!connectEdge(edge = edges[i], x0, y0, x1, y1) + || !clipEdge(edge, x0, y0, x1, y1) + || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4 + || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) { + delete edges[i]; + } + } +} - var c1 = cr * n2n2 / determinant, - c2 = -cr * n1n2 / determinant, - n1xn2 = cartesianCross(n1, n2), - A = cartesianScale(n1, c1), - B = cartesianScale(n2, c2); - cartesianAddInPlace(A, B); +function createCell(site) { + return cells[site.index] = { + site: site, + halfedges: [] + }; +} - // Solve |p(t)|^2 = 1. - var u = n1xn2, - w = cartesianDot(A, u), - uu = cartesianDot(u, u), - t2 = w * w - uu * (cartesianDot(A, A) - 1); +function cellHalfedgeAngle(cell, edge) { + var site = cell.site, + va = edge.left, + vb = edge.right; + if (site === vb) vb = va, va = site; + if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]); + if (site === va) va = edge[1], vb = edge[0]; + else va = edge[0], vb = edge[1]; + return Math.atan2(va[0] - vb[0], vb[1] - va[1]); +} - if (t2 < 0) return; +function cellHalfedgeStart(cell, edge) { + return edge[+(edge.left !== cell.site)]; +} - var t = sqrt$1(t2), - q = cartesianScale(u, (-w - t) / uu); - cartesianAddInPlace(q, A); - q = spherical(q); +function cellHalfedgeEnd(cell, edge) { + return edge[+(edge.left === cell.site)]; +} - if (!two) return q; +function sortCellHalfedges() { + for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { + if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { + var index = new Array(m), + array = new Array(m); + for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]); + index.sort(function(i, j) { return array[j] - array[i]; }); + for (j = 0; j < m; ++j) array[j] = halfedges[index[j]]; + for (j = 0; j < m; ++j) halfedges[j] = array[j]; + } + } +} - // Two intersection points. - var lambda0 = a[0], - lambda1 = b[0], - phi0 = a[1], - phi1 = b[1], - z; +function clipCells(x0, y0, x1, y1) { + var nCells = cells.length, + iCell, + cell, + site, + iHalfedge, + halfedges, + nHalfedges, + start, + startX, + startY, + end, + endX, + endY, + cover = true; - if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + halfedges = cell.halfedges; + iHalfedge = halfedges.length; - var delta = lambda1 - lambda0, - polar = abs(delta - pi$4) < epsilon$4, - meridian = polar || delta < epsilon$4; + // Remove any dangling clipped edges. + while (iHalfedge--) { + if (!edges[halfedges[iHalfedge]]) { + halfedges.splice(iHalfedge, 1); + } + } - if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; + // Insert any border edges as necessary. + iHalfedge = 0, nHalfedges = halfedges.length; + while (iHalfedge < nHalfedges) { + end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1]; + start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; + if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) { + halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, + Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1] + : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1] + : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0] + : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0] + : null)) - 1); + ++nHalfedges; + } + } - // Check that the first point is between a and b. - if (meridian - ? polar - ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$4 ? phi0 : phi1) - : phi0 <= q[1] && q[1] <= phi1 - : delta > pi$4 ^ (lambda0 <= q[0] && q[0] <= lambda1)) { - var q1 = cartesianScale(u, (-w + t) / uu); - cartesianAddInPlace(q1, A); - return [q, spherical(q1)]; + if (nHalfedges) cover = false; } } - // Generates a 4-bit vector representing the location of a point relative to - // the small circle's bounding box. - function code(lambda, phi) { - var r = smallRadius ? radius : pi$4 - radius, - code = 0; - if (lambda < -r) code |= 1; // left - else if (lambda > r) code |= 2; // right - if (phi < -r) code |= 4; // below - else if (phi > r) code |= 8; // above - return code; + // If there weren’t any edges, have the closest site cover the extent. + // It doesn’t matter which corner of the extent we measure! + if (cover) { + var dx, dy, d2, dc = Infinity; + + for (iCell = 0, cover = null; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + dx = site[0] - x0; + dy = site[1] - y0; + d2 = dx * dx + dy * dy; + if (d2 < dc) dc = d2, cover = cell; + } + } + + if (cover) { + var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; + cover.halfedges.push( + edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, + edges.push(createBorderEdge(site, v01, v11)) - 1, + edges.push(createBorderEdge(site, v11, v10)) - 1, + edges.push(createBorderEdge(site, v10, v00)) - 1 + ); + } } - return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$4, radius - pi$4]); -}; + // Lastly delete any cells with no edges; these were entirely clipped. + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + if (!cell.halfedges.length) { + delete cells[iCell]; + } + } + } +} -var transform$1 = function(methods) { - return { - stream: transformer(methods) - }; -}; +var circlePool = []; -function transformer(methods) { - return function(stream) { - var s = new TransformStream; - for (var key in methods) s[key] = methods[key]; - s.stream = stream; - return s; - }; +var firstCircle; + +function Circle() { + RedBlackNode(this); + this.x = + this.y = + this.arc = + this.site = + this.cy = null; } -function TransformStream() {} +function attachCircle(arc) { + var lArc = arc.P, + rArc = arc.N; -TransformStream.prototype = { - constructor: TransformStream, - 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(); } -}; + if (!lArc || !rArc) return; + + var lSite = lArc.site, + cSite = arc.site, + rSite = rArc.site; + + if (lSite === rSite) return; -function fitExtent(projection, extent, object) { - var w = extent[1][0] - extent[0][0], - h = extent[1][1] - extent[0][1], - clip = projection.clipExtent && projection.clipExtent(); + var bx = cSite[0], + by = cSite[1], + ax = lSite[0] - bx, + ay = lSite[1] - by, + cx = rSite[0] - bx, + cy = rSite[1] - by; - projection - .scale(150) - .translate([0, 0]); + var d = 2 * (ax * cy - ay * cx); + if (d >= -epsilon2$2) return; - if (clip != null) projection.clipExtent(null); + var ha = ax * ax + ay * ay, + hc = cx * cx + cy * cy, + x = (cy * ha - ay * hc) / d, + y = (ax * hc - cx * ha) / d; - geoStream(object, projection.stream(boundsStream$1)); + var circle = circlePool.pop() || new Circle; + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom - var b = boundsStream$1.result(), - k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), - x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, - y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; + arc.circle = circle; - if (clip != null) projection.clipExtent(clip); + var before = null, + node = circles._; - return projection - .scale(k * 150) - .translate([x, y]); -} + 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 fitSize(projection, size, object) { - return fitExtent(projection, [[0, 0], size], object); + circles.insert(before, circle); + if (!before) firstCircle = circle; } -var maxDepth = 16; -var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance) +function detachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) firstCircle = circle.N; + circles.remove(circle); + circlePool.push(circle); + RedBlackNode(circle); + arc.circle = null; + } +} -var resample = function(project, delta2) { - return +delta2 ? resample$1(project, delta2) : resampleNone(project); -}; +var beachPool = []; -function resampleNone(project) { - return transformer({ - point: function(x, y) { - x = project(x, y); - this.stream.point(x[0], x[1]); - } - }); +function Beach() { + RedBlackNode(this); + this.edge = + this.site = + this.circle = null; } -function resample$1(project, delta2) { +function createBeach(site) { + var beach = beachPool.pop() || new Beach; + beach.site = site; + return beach; +} - function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, - dy = y1 - y0, - d2 = dx * dx + dy * dy; - if (d2 > 4 * delta2 && depth--) { - var a = a0 + a1, - b = b0 + b1, - c = c0 + c1, - m = sqrt$1(a * a + b * b + c * c), - phi2 = asin$1(c /= m), - lambda2 = abs(abs(c) - 1) < epsilon$4 || abs(lambda0 - lambda1) < epsilon$4 ? (lambda0 + lambda1) / 2 : atan2(b, a), - p = project(lambda2, phi2), - x2 = p[0], - y2 = p[1], - dx2 = x2 - x0, - dy2 = y2 - y0, - dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > delta2 // perpendicular projected distance - || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end - || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance - resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); - } - } - } - return function(stream) { - var lambda00, x00, y00, a00, b00, c00, // first point - lambda0, x0, y0, a0, b0, c0; // previous point +function detachBeach(beach) { + detachCircle(beach); + beaches.remove(beach); + beachPool.push(beach); + RedBlackNode(beach); +} - var resampleStream = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; }, - polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; } - }; +function removeBeach(beach) { + var circle = beach.circle, + x = circle.x, + y = circle.cy, + vertex = [x, y], + previous = beach.P, + next = beach.N, + disappearing = [beach]; - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } + detachBeach(beach); - function lineStart() { - x0 = NaN; - resampleStream.point = linePoint; - stream.lineStart(); - } + var lArc = previous; + while (lArc.circle + && Math.abs(x - lArc.circle.x) < epsilon$4 + && Math.abs(y - lArc.circle.cy) < epsilon$4) { + previous = lArc.P; + disappearing.unshift(lArc); + detachBeach(lArc); + lArc = previous; + } - function linePoint(lambda, phi) { - var c = cartesian([lambda, phi]), p = project(lambda, phi); - resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } + disappearing.unshift(lArc); + detachCircle(lArc); - function lineEnd() { - resampleStream.point = point; - stream.lineEnd(); - } + var rArc = next; + while (rArc.circle + && Math.abs(x - rArc.circle.x) < epsilon$4 + && Math.abs(y - rArc.circle.cy) < epsilon$4) { + next = rArc.N; + disappearing.push(rArc); + detachBeach(rArc); + rArc = next; + } - function ringStart() { - lineStart(); - resampleStream.point = ringPoint; - resampleStream.lineEnd = ringEnd; - } + disappearing.push(rArc); + detachCircle(rArc); - function ringPoint(lambda, phi) { - linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resampleStream.point = linePoint; - } + var nArcs = disappearing.length, + iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } - function ringEnd() { - resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); - resampleStream.lineEnd = lineEnd; - lineEnd(); - } + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = createEdge(lArc.site, rArc.site, null, vertex); - return resampleStream; - }; + attachCircle(lArc); + attachCircle(rArc); } -var transformRadians = transformer({ - point: function(x, y) { - this.stream.point(x * radians, y * radians); +function addBeach(site) { + var x = site[0], + directrix = site[1], + lArc, + rArc, + dxl, + dxr, + node = beaches._; + + while (node) { + dxl = leftBreakPoint(node, directrix) - x; + if (dxl > epsilon$4) node = node.L; else { + dxr = x - rightBreakPoint(node, directrix); + if (dxr > epsilon$4) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -epsilon$4) { + lArc = node.P; + rArc = node; + } else if (dxr > -epsilon$4) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } } -}); -function projection(project) { - return projectionMutator(function() { return project; })(); -} + createCell(site); + var newArc = createBeach(site); + beaches.insert(lArc, newArc); -function projectionMutator(projectAt) { - var project, - k = 150, // scale - x = 480, y = 250, // translate - dx, dy, lambda = 0, phi = 0, // center - deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate - theta = null, preclip = clipAntimeridian, // clip angle - x0 = null, y0, x1, y1, postclip = identity$7, // clip extent - delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision - cache, - cacheStream; + if (!lArc && !rArc) return; - function projection(point) { - point = projectRotate(point[0] * radians, point[1] * radians); - return [point[0] * k + dx, dy - point[1] * k]; + if (lArc === rArc) { + detachCircle(lArc); + rArc = createBeach(lArc.site); + beaches.insert(newArc, rArc); + newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site); + attachCircle(lArc); + attachCircle(rArc); + return; } - function invert(point) { - point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); - return point && [point[0] * degrees$1, point[1] * degrees$1]; + if (!rArc) { // && lArc + newArc.edge = createEdge(lArc.site, newArc.site); + return; } - function projectTransform(x, y) { - return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; - } + // else lArc !== rArc + detachCircle(lArc); + detachCircle(rArc); - projection.stream = function(stream) { - return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream)))); - }; + var lSite = lArc.site, + ax = lSite[0], + ay = lSite[1], + bx = site[0] - ax, + by = site[1] - ay, + rSite = rArc.site, + cx = rSite[0] - ax, + cy = rSite[1] - ay, + d = 2 * (bx * cy - by * cx), + hb = bx * bx + by * by, + hc = cx * cx + cy * cy, + vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay]; - projection.clipAngle = function(_) { - return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1; - }; + setEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = createEdge(lSite, site, null, vertex); + rArc.edge = createEdge(site, rSite, null, vertex); + attachCircle(lArc); + attachCircle(rArc); +} - projection.clipExtent = function(_) { - return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$7) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; - }; +function leftBreakPoint(arc, directrix) { + var site = arc.site, + rfocx = site[0], + rfocy = site[1], + pby2 = rfocy - directrix; - projection.scale = function(_) { - return arguments.length ? (k = +_, recenter()) : k; - }; + if (!pby2) return rfocx; - projection.translate = function(_) { - return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; - }; + var lArc = arc.P; + if (!lArc) return -Infinity; - projection.center = function(_) { - return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1]; - }; + site = lArc.site; + var lfocx = site[0], + lfocy = site[1], + plby2 = lfocy - directrix; - projection.rotate = function(_) { - return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1]; - }; + if (!plby2) return lfocx; - projection.precision = function(_) { - return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt$1(delta2); - }; + var hl = lfocx - rfocx, + aby2 = 1 / pby2 - 1 / plby2, + b = hl / plby2; - projection.fitExtent = function(extent, object) { - return fitExtent(projection, extent, object); - }; + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - projection.fitSize = function(size, object) { - return fitSize(projection, size, object); - }; + return (rfocx + lfocx) / 2; +} - function recenter() { - projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project); - var center = project(lambda, phi); - dx = x - center[0] * k; - dy = y + center[1] * k; - return reset(); - } +function rightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return leftBreakPoint(rArc, directrix); + var site = arc.site; + return site[1] === directrix ? site[0] : Infinity; +} - function reset() { - cache = cacheStream = null; - return projection; - } +var epsilon$4 = 1e-6; +var epsilon2$2 = 1e-12; +var beaches; +var cells; +var circles; +var edges; - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return recenter(); - }; +function triangleArea(a, b, c) { + return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); } -function conicProjection(projectAt) { - var phi0 = 0, - phi1 = pi$4 / 3, - m = projectionMutator(projectAt), - p = m(phi0, phi1); +function lexicographic(a, b) { + return b[1] - a[1] + || b[0] - a[0]; +} - p.parallels = function(_) { - return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1]; - }; +function Diagram(sites, extent) { + var site = sites.sort(lexicographic).pop(), + x, + y, + circle; - return p; -} + edges = []; + cells = new Array(sites.length); + beaches = new RedBlackTree; + circles = new RedBlackTree; -function cylindricalEqualAreaRaw(phi0) { - var cosPhi0 = cos$1(phi0); + while (true) { + circle = firstCircle; + if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { + if (site[0] !== x || site[1] !== y) { + addBeach(site); + x = site[0], y = site[1]; + } + site = sites.pop(); + } else if (circle) { + removeBeach(circle.arc); + } else { + break; + } + } - function forward(lambda, phi) { - return [lambda * cosPhi0, sin$1(phi) / cosPhi0]; + sortCellHalfedges(); + + if (extent) { + var x0 = +extent[0][0], + y0 = +extent[0][1], + x1 = +extent[1][0], + y1 = +extent[1][1]; + clipEdges(x0, y0, x1, y1); + clipCells(x0, y0, x1, y1); } - forward.invert = function(x, y) { - return [x / cosPhi0, asin$1(y * cosPhi0)]; - }; + this.edges = edges; + this.cells = cells; - return forward; + beaches = + circles = + edges = + cells = null; } -function conicEqualAreaRaw(y0, y1) { - var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2; +Diagram.prototype = { + constructor: Diagram, - // Are the parallels symmetrical around the Equator? - if (abs(n) < epsilon$4) return cylindricalEqualAreaRaw(y0); + polygons: function() { + var edges = this.edges; - var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt$1(c) / n; + return this.cells.map(function(cell) { + var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); }); + polygon.data = cell.site.data; + return polygon; + }); + }, - function project(x, y) { - var r = sqrt$1(c - 2 * n * sin$1(y)) / n; - return [r * sin$1(x *= n), r0 - r * cos$1(x)]; - } + triangles: function() { + var triangles = [], + edges = this.edges; - project.invert = function(x, y) { - var r0y = r0 - y; - return [atan2(x, abs(r0y)) / n * sign$1(r0y), asin$1((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; - }; + this.cells.forEach(function(cell, i) { + if (!(m = (halfedges = cell.halfedges).length)) return; + var site = cell.site, + halfedges, + j = -1, + m, + s0, + e1 = edges[halfedges[m - 1]], + s1 = e1.left === site ? e1.right : e1.left; - return project; -} + while (++j < m) { + s0 = s1; + e1 = edges[halfedges[j]]; + s1 = e1.left === site ? e1.right : e1.left; + if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { + triangles.push([site.data, s0.data, s1.data]); + } + } + }); -var conicEqualArea = function() { - return conicProjection(conicEqualAreaRaw) - .scale(155.424) - .center([0, 33.6442]); -}; + return triangles; + }, -var albers = function() { - return conicEqualArea() - .parallels([29.5, 45.5]) - .scale(1070) - .translate([480, 250]) - .rotate([96, 0]) - .center([-0.6, 38.7]); -}; + links: function() { + return this.edges.filter(function(edge) { + return edge.right; + }).map(function(edge) { + return { + source: edge.left.data, + target: edge.right.data + }; + }); + }, -// The projections must have mutually exclusive clip regions on the sphere, -// as this will avoid emitting interleaving lines and polygons. -function multiplex(streams) { - var n = streams.length; - return { - point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); }, - sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); }, - lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); }, - lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); }, - polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); }, - polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); } - }; -} + find: function(x, y, radius) { + var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell; + + // Use the previously-found cell, or start with an arbitrary one. + while (!(cell = that.cells[i1])) if (++i1 >= n) return null; + var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy; + + // Traverse the half-edges to find a closer cell, if any. + do { + cell = that.cells[i0 = i1], i1 = null; + cell.halfedges.forEach(function(e) { + var edge = that.edges[e], v = edge.left; + if ((v === cell.site || !v) && !(v = edge.right)) return; + var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy; + if (v2 < d2) d2 = v2, i1 = v.index; + }); + } while (i1 !== null); + + that._found = i0; -// A composite projection for the United States, configured by default for -// 960×500. The projection also works quite well at 960×600 if you change the -// scale to 1285 and adjust the translate accordingly. The set of standard -// parallels for each region comes from USGS, which is published here: -// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers -var albersUsa = function() { - var cache, - cacheStream, - lower48 = albers(), lower48Point, - alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 - hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 - point, pointStream = {point: function(x, y) { point = [x, y]; }}; + return radius == null || d2 <= radius * radius ? cell.site : null; + } +}; - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - return point = null, - (lower48Point.point(x, y), point) - || (alaskaPoint.point(x, y), point) - || (hawaiiPoint.point(x, y), point); +var voronoi = function() { + var x$$1 = x$4, + y$$1 = y$4, + extent = null; + + function voronoi(data) { + return new Diagram(data.map(function(d, i) { + var s = [Math.round(x$$1(d, i, data) / epsilon$4) * epsilon$4, Math.round(y$$1(d, i, data) / epsilon$4) * epsilon$4]; + s.index = i; + s.data = d; + return s; + }), extent); } - 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 >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska - : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii - : lower48).invert(coordinates); + voronoi.polygons = function(data) { + return voronoi(data).polygons(); }; - albersUsa.stream = function(stream) { - return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); + voronoi.links = function(data) { + return voronoi(data).links(); }; - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_), alaska.precision(_), hawaii.precision(_); - return reset(); + voronoi.triangles = function(data) { + return voronoi(data).triangles(); }; - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_); - return albersUsa.translate(lower48.translate()); + voronoi.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : x$$1; }; - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - - lower48Point = lower48 - .translate(_) - .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) - .stream(pointStream); - - alaskaPoint = alaska - .translate([x - 0.307 * k, y + 0.201 * k]) - .clipExtent([[x - 0.425 * k + epsilon$4, y + 0.120 * k + epsilon$4], [x - 0.214 * k - epsilon$4, y + 0.234 * k - epsilon$4]]) - .stream(pointStream); - - hawaiiPoint = hawaii - .translate([x - 0.205 * k, y + 0.212 * k]) - .clipExtent([[x - 0.214 * k + epsilon$4, y + 0.166 * k + epsilon$4], [x - 0.115 * k - epsilon$4, y + 0.234 * k - epsilon$4]]) - .stream(pointStream); - - return reset(); + voronoi.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : y$$1; }; - albersUsa.fitExtent = function(extent, object) { - return fitExtent(albersUsa, extent, object); + voronoi.extent = function(_) { + return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]]; }; - albersUsa.fitSize = function(size, object) { - return fitSize(albersUsa, size, object); + voronoi.size = function(_) { + return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]]; }; - function reset() { - cache = cacheStream = null; - return albersUsa; - } + return voronoi; +}; - return albersUsa.scale(1070); +var constant$12 = function(x) { + return function() { + return x; + }; }; -function azimuthalRaw(scale) { - return function(x, y) { - var cx = cos$1(x), - cy = cos$1(y), - k = scale(cx * cy); - return [ - k * cy * sin$1(x), - k * sin$1(y) - ]; - } +function ZoomEvent(target, type, transform) { + this.target = target; + this.type = type; + this.transform = transform; } -function azimuthalInvert(angle) { - return function(x, y) { - var z = sqrt$1(x * x + y * y), - c = angle(z), - sc = sin$1(c), - cc = cos$1(c); - return [ - atan2(x * sc, z * cc), - asin$1(z && y * sc / z) - ]; - } +function Transform(k, x, y) { + this.k = k; + this.x = x; + this.y = y; } -var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { - return sqrt$1(2 / (1 + cxcy)); -}); +Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x, y) { + return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x) { + return x * this.k + this.x; + }, + applyY: function(y) { + return y * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x) { + return (x - this.x) / this.k; + }, + invertY: function(y) { + return (y - this.y) / this.k; + }, + rescaleX: function(x) { + return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); + }, + rescaleY: function(y) { + return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } +}; -azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { - return 2 * asin$1(z / 2); -}); +var identity$8 = new Transform(1, 0, 0); -var azimuthalEqualArea = function() { - return projection(azimuthalEqualAreaRaw) - .scale(124.75) - .clipAngle(180 - 1e-3); -}; +transform$1.prototype = Transform.prototype; -var azimuthalEquidistantRaw = azimuthalRaw(function(c) { - return (c = acos(c)) && c / sin$1(c); -}); +function transform$1(node) { + return node.__zoom || identity$8; +} -azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { - return z; -}); +function nopropagation$2() { + exports.event.stopImmediatePropagation(); +} -var azimuthalEquidistant = function() { - return projection(azimuthalEquidistantRaw) - .scale(79.4188) - .clipAngle(180 - 1e-3); +var noevent$2 = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); }; -function mercatorRaw(lambda, phi) { - return [lambda, log$1(tan((halfPi$3 + phi) / 2))]; +// Ignore right-click, since that should open the context menu. +function defaultFilter$2() { + return !exports.event.button; } -mercatorRaw.invert = function(x, y) { - return [x, 2 * atan(exp(y)) - halfPi$3]; -}; +function defaultExtent$1() { + var e = this, w, h; + if (e instanceof SVGElement) { + e = e.ownerSVGElement || e; + w = e.width.baseVal.value; + h = e.height.baseVal.value; + } else { + w = e.clientWidth; + h = e.clientHeight; + } + return [[0, 0], [w, h]]; +} -var mercator = function() { - return mercatorProjection(mercatorRaw) - .scale(961 / tau$4); -}; +function defaultTransform() { + return this.__zoom || identity$8; +} -function mercatorProjection(project) { - var m = projection(project), - scale = m.scale, - translate = m.translate, - clipExtent = m.clipExtent, - clipAuto; +var zoom = function() { + var filter = defaultFilter$2, + extent = defaultExtent$1, + k0 = 0, + k1 = Infinity, + x0 = -k1, + x1 = k1, + y0 = x0, + y1 = x1, + duration = 250, + interpolate$$1 = interpolateZoom, + gestures = [], + listeners = dispatch("start", "zoom", "end"), + touchstarting, + touchending, + touchDelay = 500, + wheelDelay = 150; - m.scale = function(_) { - return arguments.length ? (scale(_), clipAuto && m.clipExtent(null), m) : scale(); + function zoom(selection$$1) { + selection$$1 + .on("wheel.zoom", wheeled) + .on("mousedown.zoom", mousedowned) + .on("dblclick.zoom", dblclicked) + .on("touchstart.zoom", touchstarted) + .on("touchmove.zoom", touchmoved) + .on("touchend.zoom touchcancel.zoom", touchended) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") + .property("__zoom", defaultTransform); + } + + zoom.transform = function(collection, transform) { + var selection$$1 = collection.selection ? collection.selection() : collection; + selection$$1.property("__zoom", defaultTransform); + if (collection !== selection$$1) { + schedule(collection, transform); + } else { + selection$$1.interrupt().each(function() { + gesture(this, arguments) + .start() + .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform) + .end(); + }); + } + }; + + zoom.scaleBy = function(selection$$1, k) { + zoom.scaleTo(selection$$1, function() { + var k0 = this.__zoom.k, + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return k0 * k1; + }); }; - m.translate = function(_) { - return arguments.length ? (translate(_), clipAuto && m.clipExtent(null), m) : translate(); + zoom.scaleTo = function(selection$$1, k) { + zoom.transform(selection$$1, function() { + var e = extent.apply(this, arguments), + t0 = this.__zoom, + p0 = centroid(e), + p1 = t0.invert(p0), + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return constrain(translate(scale(t0, k1), p0, p1), e); + }); }; - m.clipExtent = function(_) { - if (!arguments.length) return clipAuto ? null : clipExtent(); - if (clipAuto = _ == null) { - var k = pi$4 * scale(), - t = translate(); - _ = [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]]; - } - clipExtent(_); - return m; + zoom.translateBy = function(selection$$1, x, y) { + zoom.transform(selection$$1, function() { + return constrain(this.__zoom.translate( + typeof x === "function" ? x.apply(this, arguments) : x, + typeof y === "function" ? y.apply(this, arguments) : y + ), extent.apply(this, arguments)); + }); }; - return m.clipExtent(null); -} + function scale(transform, k) { + k = Math.max(k0, Math.min(k1, k)); + return k === transform.k ? transform : new Transform(k, transform.x, transform.y); + } -function tany(y) { - return tan((halfPi$3 + y) / 2); -} + function translate(transform, p0, p1) { + var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k; + return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y); + } -function conicConformalRaw(y0, y1) { - var cy0 = cos$1(y0), - n = y0 === y1 ? sin$1(y0) : log$1(cy0 / cos$1(y1)) / log$1(tany(y1) / tany(y0)), - f = cy0 * pow$1(tany(y0), n) / n; + function constrain(transform, extent) { + var dx0 = transform.invertX(extent[0][0]) - x0, + dx1 = transform.invertX(extent[1][0]) - x1, + dy0 = transform.invertY(extent[0][1]) - y0, + dy1 = transform.invertY(extent[1][1]) - y1; + return transform.translate( + dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), + dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) + ); + } - if (!n) return mercatorRaw; + function centroid(extent) { + return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; + } - function project(x, y) { - if (f > 0) { if (y < -halfPi$3 + epsilon$4) y = -halfPi$3 + epsilon$4; } - else { if (y > halfPi$3 - epsilon$4) y = halfPi$3 - epsilon$4; } - var r = f / pow$1(tany(y), n); - return [r * sin$1(n * x), f - r * cos$1(n * x)]; + function schedule(transition$$1, transform, center) { + transition$$1 + .on("start.zoom", function() { gesture(this, arguments).start(); }) + .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); }) + .tween("zoom", function() { + var that = this, + args = arguments, + g = gesture(that, args), + e = extent.apply(that, args), + p = center || centroid(e), + w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), + a = that.__zoom, + b = typeof transform === "function" ? transform.apply(that, args) : transform, + i = interpolate$$1(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); + return function(t) { + if (t === 1) t = b; // Avoid rounding error on end. + else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } + g.zoom(null, t); + }; + }); } - project.invert = function(x, y) { - var fy = f - y, r = sign$1(n) * sqrt$1(x * x + fy * fy); - return [atan2(x, abs(fy)) / n * sign$1(fy), 2 * atan(pow$1(f / r, 1 / n)) - halfPi$3]; - }; + function gesture(that, args) { + for (var i = 0, n = gestures.length, g; i < n; ++i) { + if ((g = gestures[i]).that === that) { + return g; + } + } + return new Gesture(that, args); + } - return project; -} + function Gesture(that, args) { + this.that = that; + this.args = args; + this.index = -1; + this.active = 0; + this.extent = extent.apply(that, args); + } -var conicConformal = function() { - return conicProjection(conicConformalRaw) - .scale(109.5) - .parallels([30, 30]); -}; + Gesture.prototype = { + start: function() { + if (++this.active === 1) { + this.index = gestures.push(this) - 1; + this.emit("start"); + } + return this; + }, + zoom: function(key, transform) { + if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]); + if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]); + if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]); + this.that.__zoom = transform; + this.emit("zoom"); + return this; + }, + end: function() { + if (--this.active === 0) { + gestures.splice(this.index, 1); + this.index = -1; + this.emit("end"); + } + return this; + }, + emit: function(type) { + customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); + } + }; -function equirectangularRaw(lambda, phi) { - return [lambda, phi]; -} + function wheeled() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + t = this.__zoom, + k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -exports.event.deltaY * (exports.event.deltaMode ? 120 : 1) / 500))), + p = mouse(this); -equirectangularRaw.invert = equirectangularRaw; + // If the mouse is in the same location as before, reuse it. + // If there were recent wheel events, reset the wheel idle timeout. + if (g.wheel) { + if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { + g.mouse[1] = t.invert(g.mouse[0] = p); + } + clearTimeout(g.wheel); + } -var equirectangular = function() { - return projection(equirectangularRaw) - .scale(152.63); -}; + // If this wheel event won’t trigger a transform change, ignore it. + else if (t.k === k) return; -function conicEquidistantRaw(y0, y1) { - var cy0 = cos$1(y0), - n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0), - g = cy0 / n + y0; + // Otherwise, capture the mouse point and location at the start. + else { + g.mouse = [p, t.invert(p)]; + interrupt(this); + g.start(); + } - if (abs(n) < epsilon$4) return equirectangularRaw; + noevent$2(); + g.wheel = setTimeout(wheelidled, wheelDelay); + g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent)); - function project(x, y) { - var gy = g - y, nx = n * x; - return [gy * sin$1(nx), g - gy * cos$1(nx)]; + function wheelidled() { + g.wheel = null; + g.end(); + } } - project.invert = function(x, y) { - var gy = g - y; - return [atan2(x, abs(gy)) / n * sign$1(gy), g - sign$1(n) * sqrt$1(x * x + gy * gy)]; - }; - - return project; -} - -var conicEquidistant = function() { - return conicProjection(conicEquidistantRaw) - .scale(131.154) - .center([0, 13.9389]); -}; - -function gnomonicRaw(x, y) { - var cy = cos$1(y), k = cos$1(x) * cy; - return [cy * sin$1(x) / k, sin$1(y) / k]; -} + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + v = select(exports.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), + p = mouse(this); -gnomonicRaw.invert = azimuthalInvert(atan); + dragDisable(exports.event.view); + nopropagation$2(); + g.mouse = [p, this.__zoom.invert(p)]; + interrupt(this); + g.start(); -var gnomonic = function() { - return projection(gnomonicRaw) - .scale(144.049) - .clipAngle(60); -}; + function mousemoved() { + noevent$2(); + g.moved = true; + g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent)); + } -function scaleTranslate(k, tx, ty) { - return k === 1 && tx === 0 && ty === 0 ? identity$7 : transformer({ - point: function(x, y) { - this.stream.point(x * k + tx, y * k + ty); + function mouseupped() { + v.on("mousemove.zoom mouseup.zoom", null); + yesdrag(exports.event.view, g.moved); + noevent$2(); + g.end(); } - }); -} + } -var identity$8 = function() { - var k = 1, tx = 0, ty = 0, transform = identity$7, // scale and translate - x0 = null, y0, x1, y1, clip = identity$7, // clip extent - cache, - cacheStream, - projection; + function dblclicked() { + if (!filter.apply(this, arguments)) return; + var t0 = this.__zoom, + p0 = mouse(this), + p1 = t0.invert(p0), + k1 = t0.k * (exports.event.shiftKey ? 0.5 : 2), + t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments)); - function reset() { - cache = cacheStream = null; - return projection; + noevent$2(); + if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0); + else select(this).call(zoom.transform, t1); } - return projection = { - stream: function(stream) { - return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream)); - }, - clipExtent: function(_) { - return arguments.length ? (clip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$7) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; - }, - scale: function(_) { - return arguments.length ? (transform = scaleTranslate(k = +_, tx, ty), reset()) : k; - }, - translate: function(_) { - return arguments.length ? (transform = scaleTranslate(k, tx = +_[0], ty = +_[1]), reset()) : [tx, ty]; - }, - fitExtent: function(extent, object) { - return fitExtent(projection, extent, object); - }, - fitSize: function(size, object) { - return fitSize(projection, size, object); + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + started, + n = touches$$1.length, i, t, p; + + nopropagation$2(); + for (i = 0; i < n; ++i) { + t = touches$$1[i], p = touch(this, touches$$1, t.identifier); + p = [p, this.__zoom.invert(p), t.identifier]; + if (!g.touch0) g.touch0 = p, started = true; + else if (!g.touch1) g.touch1 = p; } - }; -}; -function orthographicRaw(x, y) { - return [cos$1(y) * sin$1(x), sin$1(y)]; -} + // If this is a dbltap, reroute to the (optional) dblclick.zoom handler. + if (touchstarting) { + touchstarting = clearTimeout(touchstarting); + if (!g.touch1) { + g.end(); + p = select(this).on("dblclick.zoom"); + if (p) p.apply(this, arguments); + return; + } + } -orthographicRaw.invert = azimuthalInvert(asin$1); + if (started) { + touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); + interrupt(this); + g.start(); + } + } -var orthographic = function() { - return projection(orthographicRaw) - .scale(249.5) - .clipAngle(90 + epsilon$4); -}; + function touchmoved() { + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, t, p, l; -function stereographicRaw(x, y) { - var cy = cos$1(y), k = 1 + cos$1(x) * cy; - return [cy * sin$1(x) / k, sin$1(y) / k]; -} + noevent$2(); + if (touchstarting) touchstarting = clearTimeout(touchstarting); + for (i = 0; i < n; ++i) { + t = touches$$1[i], p = touch(this, touches$$1, t.identifier); + if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; + else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; + } + t = g.that.__zoom; + if (g.touch1) { + var p0 = g.touch0[0], l0 = g.touch0[1], + p1 = g.touch1[0], l1 = g.touch1[1], + dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, + dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; + t = scale(t, Math.sqrt(dp / dl)); + p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; + l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; + } + else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; + else return; + g.zoom("touch", constrain(translate(t, p, l), g.extent)); + } -stereographicRaw.invert = azimuthalInvert(function(z) { - return 2 * atan(z); -}); + function touchended() { + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, t; -var stereographic = function() { - return projection(stereographicRaw) - .scale(250) - .clipAngle(142); -}; + nopropagation$2(); + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, touchDelay); + for (i = 0; i < n; ++i) { + t = touches$$1[i]; + if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; + else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; + } + if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; + if (!g.touch0) g.end(); + } -function transverseMercatorRaw(lambda, phi) { - return [log$1(tan((halfPi$3 + phi) / 2)), -lambda]; -} + zoom.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$12(!!_), zoom) : filter; + }; -transverseMercatorRaw.invert = function(x, y) { - return [-y, 2 * atan(exp(x)) - halfPi$3]; -}; + zoom.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$12([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; + }; -var transverseMercator = function() { - var m = mercatorProjection(transverseMercatorRaw), - center = m.center, - rotate = m.rotate; + zoom.scaleExtent = function(_) { + return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1]; + }; - m.center = function(_) { - return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); + zoom.translateExtent = function(_) { + return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]]; }; - m.rotate = function(_) { - return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); + zoom.duration = function(_) { + return arguments.length ? (duration = +_, zoom) : duration; }; - return rotate([0, 0, 90]) - .scale(159.155); + zoom.interpolate = function(_) { + return arguments.length ? (interpolate$$1 = _, zoom) : interpolate$$1; + }; + + zoom.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? zoom : value; + }; + + return zoom; }; exports.version = version; @@ -16021,7 +16031,7 @@ exports.min = min; exports.pairs = pairs; exports.permute = permute; exports.quantile = threshold; -exports.range = range; +exports.range = sequence; exports.scan = scan; exports.shuffle = shuffle; exports.sum = sum; @@ -16030,81 +16040,251 @@ exports.tickStep = tickStep; exports.transpose = transpose; exports.variance = variance; exports.zip = zip; -exports.entries = entries; +exports.axisTop = axisTop; +exports.axisRight = axisRight; +exports.axisBottom = axisBottom; +exports.axisLeft = axisLeft; +exports.brush = brush; +exports.brushX = brushX; +exports.brushY = brushY; +exports.brushSelection = brushSelection; +exports.chord = chord; +exports.ribbon = ribbon; +exports.nest = nest; +exports.set = set$2; +exports.map = map$1; exports.keys = keys; exports.values = values; -exports.map = map$1; -exports.set = set; -exports.nest = nest; +exports.entries = entries; +exports.color = color; +exports.rgb = rgb; +exports.hsl = hsl; +exports.lab = lab; +exports.hcl = hcl; +exports.cubehelix = cubehelix; +exports.dispatch = dispatch; +exports.drag = drag; +exports.dragDisable = dragDisable; +exports.dragEnable = yesdrag; +exports.dsvFormat = dsv; +exports.csvParse = csvParse; +exports.csvParseRows = csvParseRows; +exports.csvFormat = csvFormat; +exports.csvFormatRows = csvFormatRows; +exports.tsvParse = tsvParse; +exports.tsvParseRows = tsvParseRows; +exports.tsvFormat = tsvFormat; +exports.tsvFormatRows = tsvFormatRows; +exports.easeLinear = linear$1; +exports.easeQuad = quadInOut; +exports.easeQuadIn = quadIn; +exports.easeQuadOut = quadOut; +exports.easeQuadInOut = quadInOut; +exports.easeCubic = cubicInOut; +exports.easeCubicIn = cubicIn; +exports.easeCubicOut = cubicOut; +exports.easeCubicInOut = cubicInOut; +exports.easePoly = polyInOut; +exports.easePolyIn = polyIn; +exports.easePolyOut = polyOut; +exports.easePolyInOut = polyInOut; +exports.easeSin = sinInOut; +exports.easeSinIn = sinIn; +exports.easeSinOut = sinOut; +exports.easeSinInOut = sinInOut; +exports.easeExp = expInOut; +exports.easeExpIn = expIn; +exports.easeExpOut = expOut; +exports.easeExpInOut = expInOut; +exports.easeCircle = circleInOut; +exports.easeCircleIn = circleIn; +exports.easeCircleOut = circleOut; +exports.easeCircleInOut = circleInOut; +exports.easeBounce = bounceOut; +exports.easeBounceIn = bounceIn; +exports.easeBounceOut = bounceOut; +exports.easeBounceInOut = bounceInOut; +exports.easeBack = backInOut; +exports.easeBackIn = backIn; +exports.easeBackOut = backOut; +exports.easeBackInOut = backInOut; +exports.easeElastic = elasticOut; +exports.easeElasticIn = elasticIn; +exports.easeElasticOut = elasticOut; +exports.easeElasticInOut = elasticInOut; +exports.forceCenter = center$1; +exports.forceCollide = collide; +exports.forceLink = link; +exports.forceManyBody = manyBody; +exports.forceSimulation = simulation; +exports.forceX = x$2; +exports.forceY = y$2; +exports.formatDefaultLocale = defaultLocale; +exports.formatLocale = formatLocale; +exports.formatSpecifier = formatSpecifier; +exports.precisionFixed = precisionFixed; +exports.precisionPrefix = precisionPrefix; +exports.precisionRound = precisionRound; +exports.geoArea = area; +exports.geoBounds = bounds; +exports.geoCentroid = centroid; +exports.geoCircle = circle; +exports.geoClipExtent = extent$1; +exports.geoDistance = distance; +exports.geoGraticule = graticule; +exports.geoGraticule10 = graticule10; +exports.geoInterpolate = interpolate$1; +exports.geoLength = length$1; +exports.geoPath = index$1; +exports.geoAlbers = albers; +exports.geoAlbersUsa = albersUsa; +exports.geoAzimuthalEqualArea = azimuthalEqualArea; +exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; +exports.geoAzimuthalEquidistant = azimuthalEquidistant; +exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; +exports.geoConicConformal = conicConformal; +exports.geoConicConformalRaw = conicConformalRaw; +exports.geoConicEqualArea = conicEqualArea; +exports.geoConicEqualAreaRaw = conicEqualAreaRaw; +exports.geoConicEquidistant = conicEquidistant; +exports.geoConicEquidistantRaw = conicEquidistantRaw; +exports.geoEquirectangular = equirectangular; +exports.geoEquirectangularRaw = equirectangularRaw; +exports.geoGnomonic = gnomonic; +exports.geoGnomonicRaw = gnomonicRaw; +exports.geoIdentity = identity$5; +exports.geoProjection = projection; +exports.geoProjectionMutator = projectionMutator; +exports.geoMercator = mercator; +exports.geoMercatorRaw = mercatorRaw; +exports.geoOrthographic = orthographic; +exports.geoOrthographicRaw = orthographicRaw; +exports.geoStereographic = stereographic; +exports.geoStereographicRaw = stereographicRaw; +exports.geoTransverseMercator = transverseMercator; +exports.geoTransverseMercatorRaw = transverseMercatorRaw; +exports.geoRotation = rotation; +exports.geoStream = geoStream; +exports.geoTransform = transform; +exports.cluster = cluster; +exports.hierarchy = hierarchy; +exports.pack = index$2; +exports.packSiblings = siblings; +exports.packEnclose = enclose; +exports.partition = partition; +exports.stratify = stratify; +exports.tree = tree; +exports.treemap = index$3; +exports.treemapBinary = binary; +exports.treemapDice = treemapDice; +exports.treemapSlice = treemapSlice; +exports.treemapSliceDice = sliceDice; +exports.treemapSquarify = squarify; +exports.treemapResquarify = resquarify; +exports.interpolate = interpolateValue; +exports.interpolateArray = array$1; +exports.interpolateBasis = basis$1; +exports.interpolateBasisClosed = basisClosed; +exports.interpolateDate = date; +exports.interpolateNumber = reinterpolate; +exports.interpolateObject = object; +exports.interpolateRound = interpolateRound; +exports.interpolateString = interpolateString; +exports.interpolateTransformCss = interpolateTransformCss; +exports.interpolateTransformSvg = interpolateTransformSvg; +exports.interpolateZoom = interpolateZoom; +exports.interpolateRgb = interpolateRgb; +exports.interpolateRgbBasis = rgbBasis; +exports.interpolateRgbBasisClosed = rgbBasisClosed; +exports.interpolateHsl = hsl$2; +exports.interpolateHslLong = hslLong; +exports.interpolateLab = lab$1; +exports.interpolateHcl = hcl$2; +exports.interpolateHclLong = hclLong; +exports.interpolateCubehelix = cubehelix$2; +exports.interpolateCubehelixLong = cubehelixLong; +exports.quantize = quantize; +exports.path = path; +exports.polygonArea = area$1; +exports.polygonCentroid = centroid$1; +exports.polygonHull = hull; +exports.polygonContains = contains; +exports.polygonLength = length$2; +exports.quadtree = quadtree; +exports.queue = queue; exports.randomUniform = uniform; exports.randomNormal = normal; exports.randomLogNormal = logNormal; exports.randomBates = bates; exports.randomIrwinHall = irwinHall; -exports.randomExponential = exponential; -exports.easeLinear = linear; -exports.easeQuad = quadInOut; -exports.easeQuadIn = quadIn; -exports.easeQuadOut = quadOut; -exports.easeQuadInOut = quadInOut; -exports.easeCubic = cubicInOut; -exports.easeCubicIn = cubicIn; -exports.easeCubicOut = cubicOut; -exports.easeCubicInOut = cubicInOut; -exports.easePoly = polyInOut; -exports.easePolyIn = polyIn; -exports.easePolyOut = polyOut; -exports.easePolyInOut = polyInOut; -exports.easeSin = sinInOut; -exports.easeSinIn = sinIn; -exports.easeSinOut = sinOut; -exports.easeSinInOut = sinInOut; -exports.easeExp = expInOut; -exports.easeExpIn = expIn; -exports.easeExpOut = expOut; -exports.easeExpInOut = expInOut; -exports.easeCircle = circleInOut; -exports.easeCircleIn = circleIn; -exports.easeCircleOut = circleOut; -exports.easeCircleInOut = circleInOut; -exports.easeBounce = bounceOut; -exports.easeBounceIn = bounceIn; -exports.easeBounceOut = bounceOut; -exports.easeBounceInOut = bounceInOut; -exports.easeBack = backInOut; -exports.easeBackIn = backIn; -exports.easeBackOut = backOut; -exports.easeBackInOut = backInOut; -exports.easeElastic = elasticOut; -exports.easeElasticIn = elasticIn; -exports.easeElasticOut = elasticOut; -exports.easeElasticInOut = elasticInOut; -exports.polygonArea = area; -exports.polygonCentroid = centroid; -exports.polygonHull = hull; -exports.polygonContains = contains; -exports.polygonLength = length$1; -exports.path = path; -exports.quadtree = quadtree; -exports.queue = queue; +exports.randomExponential = exponential$1; +exports.request = request; +exports.html = html; +exports.json = json; +exports.text = text; +exports.xml = xml; +exports.csv = csv$1; +exports.tsv = tsv$1; +exports.scaleBand = band; +exports.scalePoint = point$1; +exports.scaleIdentity = identity$6; +exports.scaleLinear = linear$2; +exports.scaleLog = log$1; +exports.scaleOrdinal = ordinal; +exports.scaleImplicit = implicit; +exports.scalePow = pow$1; +exports.scaleSqrt = sqrt$1; +exports.scaleQuantile = quantile$$1; +exports.scaleQuantize = quantize$1; +exports.scaleThreshold = threshold$1; +exports.scaleTime = time; +exports.scaleUtc = utcTime; +exports.schemeCategory10 = category10; +exports.schemeCategory20b = category20b; +exports.schemeCategory20c = category20c; +exports.schemeCategory20 = category20; +exports.interpolateCubehelixDefault = cubehelix$3; +exports.interpolateRainbow = rainbow$1; +exports.interpolateWarm = warm; +exports.interpolateCool = cool; +exports.interpolateViridis = viridis; +exports.interpolateMagma = magma; +exports.interpolateInferno = inferno; +exports.interpolatePlasma = plasma; +exports.scaleSequential = sequential; +exports.creator = creator; +exports.local = local$1; +exports.matcher = matcher$1; +exports.mouse = mouse; +exports.namespace = namespace; +exports.namespaces = namespaces; +exports.select = select; +exports.selectAll = selectAll; +exports.selection = selection; +exports.selector = selector; +exports.selectorAll = selectorAll; +exports.touch = touch; +exports.touches = touches; +exports.window = window; +exports.customEvent = customEvent; exports.arc = arc; -exports.area = area$1; +exports.area = area$2; exports.line = line; exports.pie = pie; exports.radialArea = radialArea; exports.radialLine = radialLine$1; exports.symbol = symbol; exports.symbols = symbols; -exports.symbolCircle = circle; +exports.symbolCircle = circle$2; exports.symbolCross = cross$1; exports.symbolDiamond = diamond; exports.symbolSquare = square; exports.symbolStar = star; exports.symbolTriangle = triangle; exports.symbolWye = wye; -exports.curveBasisClosed = basisClosed; +exports.curveBasisClosed = basisClosed$1; exports.curveBasisOpen = basisOpen; -exports.curveBasis = basis; +exports.curveBasis = basis$2; exports.curveBundle = bundle; exports.curveCardinalClosed = cardinalClosed; exports.curveCardinalOpen = cardinalOpen; @@ -16122,70 +16302,23 @@ exports.curveStepAfter = stepAfter; exports.curveStepBefore = stepBefore; exports.stack = stack; exports.stackOffsetExpand = expand; -exports.stackOffsetNone = none; +exports.stackOffsetNone = none$1; exports.stackOffsetSilhouette = silhouette; exports.stackOffsetWiggle = wiggle; -exports.stackOrderAscending = ascending$1; +exports.stackOrderAscending = ascending$2; exports.stackOrderDescending = descending$2; exports.stackOrderInsideOut = insideOut; -exports.stackOrderNone = none$1; +exports.stackOrderNone = none$2; exports.stackOrderReverse = reverse; -exports.color = color; -exports.rgb = rgb; -exports.hsl = hsl; -exports.lab = lab; -exports.hcl = hcl; -exports.cubehelix = cubehelix; -exports.interpolate = interpolate; -exports.interpolateArray = array$1; -exports.interpolateDate = date; -exports.interpolateNumber = interpolateNumber; -exports.interpolateObject = object; -exports.interpolateRound = interpolateRound; -exports.interpolateString = interpolateString; -exports.interpolateTransformCss = interpolateTransformCss; -exports.interpolateTransformSvg = interpolateTransformSvg; -exports.interpolateZoom = interpolateZoom; -exports.interpolateRgb = interpolateRgb; -exports.interpolateRgbBasis = rgbBasis; -exports.interpolateRgbBasisClosed = rgbBasisClosed; -exports.interpolateHsl = hsl$2; -exports.interpolateHslLong = hslLong; -exports.interpolateLab = lab$1; -exports.interpolateHcl = hcl$2; -exports.interpolateHclLong = hclLong; -exports.interpolateCubehelix = cubehelix$2; -exports.interpolateCubehelixLong = cubehelixLong; -exports.interpolateBasis = basis$2; -exports.interpolateBasisClosed = basisClosed$1; -exports.quantize = quantize; -exports.dispatch = dispatch; -exports.dsvFormat = dsv; -exports.csvParse = csvParse; -exports.csvParseRows = csvParseRows; -exports.csvFormat = csvFormat; -exports.csvFormatRows = csvFormatRows; -exports.tsvParse = tsvParse; -exports.tsvParseRows = tsvParseRows; -exports.tsvFormat = tsvFormat; -exports.tsvFormatRows = tsvFormatRows; -exports.request = request; -exports.html = html; -exports.json = json; -exports.text = text; -exports.xml = xml; -exports.csv = csv$1; -exports.tsv = tsv$1; -exports.now = now; -exports.timer = timer; -exports.timerFlush = timerFlush; -exports.timeout = timeout$1; -exports.interval = interval$1; exports.timeInterval = newInterval; exports.timeMillisecond = millisecond; exports.timeMilliseconds = milliseconds; +exports.utcMillisecond = millisecond; +exports.utcMilliseconds = milliseconds; exports.timeSecond = second; exports.timeSeconds = seconds; +exports.utcSecond = second; +exports.utcSeconds = seconds; exports.timeMinute = minute; exports.timeMinutes = minutes; exports.timeHour = hour; @@ -16212,10 +16345,6 @@ exports.timeMonth = month; exports.timeMonths = months; exports.timeYear = year; exports.timeYears = years; -exports.utcMillisecond = millisecond; -exports.utcMilliseconds = milliseconds; -exports.utcSecond = second; -exports.utcSeconds = seconds; exports.utcMinute = utcMinute; exports.utcMinutes = utcMinutes; exports.utcHour = utcHour; @@ -16242,141 +16371,22 @@ exports.utcMonth = utcMonth; exports.utcMonths = utcMonths; exports.utcYear = utcYear; exports.utcYears = utcYears; -exports.formatLocale = formatLocale; -exports.formatDefaultLocale = defaultLocale; -exports.formatSpecifier = formatSpecifier; -exports.precisionFixed = precisionFixed; -exports.precisionPrefix = precisionPrefix; -exports.precisionRound = precisionRound; +exports.timeFormatDefaultLocale = defaultLocale$1; +exports.timeFormatLocale = formatLocale$1; exports.isoFormat = formatIso; exports.isoParse = parseIso; -exports.timeFormatLocale = formatLocale$1; -exports.timeFormatDefaultLocale = defaultLocale$1; -exports.scaleBand = band; -exports.scalePoint = point$4; -exports.scaleIdentity = identity$4; -exports.scaleLinear = linear$2; -exports.scaleLog = log; -exports.scaleOrdinal = ordinal; -exports.scaleImplicit = implicit; -exports.scalePow = pow; -exports.scaleSqrt = sqrt; -exports.scaleQuantile = quantile$$1; -exports.scaleQuantize = quantize$1; -exports.scaleThreshold = threshold$1; -exports.scaleTime = time; -exports.scaleUtc = utcTime; -exports.schemeCategory10 = category10; -exports.schemeCategory20b = category20b; -exports.schemeCategory20c = category20c; -exports.schemeCategory20 = category20; -exports.scaleSequential = sequential; -exports.interpolateCubehelixDefault = cubehelix$3; -exports.interpolateRainbow = rainbow$1; -exports.interpolateWarm = warm; -exports.interpolateCool = cool; -exports.interpolateViridis = viridis; -exports.interpolateMagma = magma; -exports.interpolateInferno = inferno; -exports.interpolatePlasma = plasma; -exports.creator = creator; -exports.customEvent = customEvent; -exports.local = local; -exports.matcher = matcher$1; -exports.mouse = mouse; -exports.namespace = namespace; -exports.namespaces = namespaces; -exports.select = select; -exports.selectAll = selectAll; -exports.selection = selection; -exports.selector = selector; -exports.selectorAll = selectorAll; -exports.touch = touch; -exports.touches = touches; -exports.window = window; +exports.now = now; +exports.timer = timer; +exports.timerFlush = timerFlush; +exports.timeout = timeout$1; +exports.interval = interval$1; +exports.transition = transition; exports.active = active; exports.interrupt = interrupt; -exports.transition = transition; -exports.axisTop = axisTop; -exports.axisRight = axisRight; -exports.axisBottom = axisBottom; -exports.axisLeft = axisLeft; -exports.cluster = cluster; -exports.hierarchy = hierarchy; -exports.pack = index; -exports.packSiblings = siblings; -exports.packEnclose = enclose; -exports.partition = partition; -exports.stratify = stratify; -exports.tree = tree; -exports.treemap = index$1; -exports.treemapBinary = binary; -exports.treemapDice = treemapDice; -exports.treemapSlice = treemapSlice; -exports.treemapSliceDice = sliceDice; -exports.treemapSquarify = squarify; -exports.treemapResquarify = resquarify; -exports.forceCenter = center$1; -exports.forceCollide = collide; -exports.forceLink = link; -exports.forceManyBody = manyBody; -exports.forceSimulation = simulation; -exports.forceX = x$3; -exports.forceY = y$3; -exports.drag = drag; -exports.dragDisable = dragDisable; -exports.dragEnable = yesdrag; exports.voronoi = voronoi; exports.zoom = zoom; -exports.zoomIdentity = identity$6; -exports.zoomTransform = transform; -exports.brush = brush; -exports.brushX = brushX; -exports.brushY = brushY; -exports.brushSelection = brushSelection; -exports.chord = chord; -exports.ribbon = ribbon; -exports.geoAlbers = albers; -exports.geoAlbersUsa = albersUsa; -exports.geoArea = area$2; -exports.geoAzimuthalEqualArea = azimuthalEqualArea; -exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; -exports.geoAzimuthalEquidistant = azimuthalEquidistant; -exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; -exports.geoBounds = bounds; -exports.geoCentroid = centroid$1; -exports.geoCircle = circle$1; -exports.geoClipExtent = extent$1; -exports.geoConicConformal = conicConformal; -exports.geoConicConformalRaw = conicConformalRaw; -exports.geoConicEqualArea = conicEqualArea; -exports.geoConicEqualAreaRaw = conicEqualAreaRaw; -exports.geoConicEquidistant = conicEquidistant; -exports.geoConicEquidistantRaw = conicEquidistantRaw; -exports.geoDistance = distance; -exports.geoEquirectangular = equirectangular; -exports.geoEquirectangularRaw = equirectangularRaw; -exports.geoGnomonic = gnomonic; -exports.geoGnomonicRaw = gnomonicRaw; -exports.geoGraticule = graticule; -exports.geoGraticule10 = graticule10; -exports.geoIdentity = identity$8; -exports.geoInterpolate = interpolate$2; -exports.geoLength = length$2; -exports.geoMercator = mercator; -exports.geoMercatorRaw = mercatorRaw; -exports.geoOrthographic = orthographic; -exports.geoOrthographicRaw = orthographicRaw; -exports.geoPath = index$3; -exports.geoProjection = projection; -exports.geoProjectionMutator = projectionMutator; -exports.geoRotation = rotation; -exports.geoStereographic = stereographic; -exports.geoStereographicRaw = stereographicRaw; -exports.geoStream = geoStream; -exports.geoTransform = transform$1; -exports.geoTransverseMercator = transverseMercator; -exports.geoTransverseMercatorRaw = transverseMercatorRaw; +exports.zoomTransform = transform$1; +exports.zoomIdentity = identity$8; Object.defineProperty(exports, '__esModule', { value: true }); From 028b4067514dc5155866418d8aeb1b50b3f97f5b Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 1 Feb 2017 14:56:26 -0800 Subject: [PATCH 17/85] Updating range rounding on band scale examples --- chapter_09/02_bar_chart_with_scales.html | 2 +- chapter_09/03_updates_all_data.html | 2 +- chapter_09/04_updates_all_data_fixed.html | 2 +- chapter_09/05_transition.html | 2 +- chapter_09/06_duration.html | 2 +- chapter_09/07_duration_slow.html | 2 +- chapter_09/08_duration_slow_labels_fixed.html | 2 +- chapter_09/09_ease_linear.html | 2 +- chapter_09/10_ease_circle.html | 2 +- chapter_09/11_ease_elastic.html | 2 +- chapter_09/12_ease_bounce.html | 2 +- chapter_09/13_delay_static.html | 2 +- chapter_09/14_delay_dynamic.html | 2 +- chapter_09/15_delay_dynamic_scaled.html | 2 +- chapter_09/16_delay_dynamic_scaled_fewer.html | 2 +- chapter_09/17_randomized_data.html | 2 +- chapter_09/18_dynamic_scale.html | 2 +- chapter_09/25_adding_values.html | 2 +- chapter_09/26_removing_values.html | 2 +- chapter_09/27_data_join_with_key.html | 2 +- chapter_09/28_adding_and_removing.html | 2 +- chapter_09/29_dynamic_labels.html | 2 +- chapter_10/01_start.html | 2 +- chapter_10/02_click.html | 2 +- chapter_10/03_hover.html | 2 +- chapter_10/04_mouseover.html | 2 +- chapter_10/05_mouseout.html | 2 +- chapter_10/06_smoother.html | 2 +- chapter_10/07_sort.html | 2 +- chapter_10/08_sort_hover.html | 2 +- chapter_10/09_resort.html | 2 +- chapter_10/10_delay.html | 2 +- chapter_10/11_browser_tooltip.html | 2 +- chapter_10/12_browser_tooltip_text.html | 2 +- chapter_10/13_svg_tooltip.html | 2 +- chapter_10/14_div_tooltip.html | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) diff --git a/chapter_09/02_bar_chart_with_scales.html b/chapter_09/02_bar_chart_with_scales.html index 631716b..b138859 100644 --- a/chapter_09/02_bar_chart_with_scales.html +++ b/chapter_09/02_bar_chart_with_scales.html @@ -20,7 +20,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/03_updates_all_data.html b/chapter_09/03_updates_all_data.html index 21e26e8..5228cc3 100644 --- a/chapter_09/03_updates_all_data.html +++ b/chapter_09/03_updates_all_data.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/04_updates_all_data_fixed.html b/chapter_09/04_updates_all_data_fixed.html index 24afc26..c099189 100644 --- a/chapter_09/04_updates_all_data_fixed.html +++ b/chapter_09/04_updates_all_data_fixed.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/05_transition.html b/chapter_09/05_transition.html index 5458dde..5eda0f7 100644 --- a/chapter_09/05_transition.html +++ b/chapter_09/05_transition.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/06_duration.html b/chapter_09/06_duration.html index 78d45f5..c67d81b 100644 --- a/chapter_09/06_duration.html +++ b/chapter_09/06_duration.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/07_duration_slow.html b/chapter_09/07_duration_slow.html index bcff852..d631100 100644 --- a/chapter_09/07_duration_slow.html +++ b/chapter_09/07_duration_slow.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/08_duration_slow_labels_fixed.html b/chapter_09/08_duration_slow_labels_fixed.html index e5d439a..ec846cb 100644 --- a/chapter_09/08_duration_slow_labels_fixed.html +++ b/chapter_09/08_duration_slow_labels_fixed.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/09_ease_linear.html b/chapter_09/09_ease_linear.html index 8aa2137..2b6336f 100644 --- a/chapter_09/09_ease_linear.html +++ b/chapter_09/09_ease_linear.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/10_ease_circle.html b/chapter_09/10_ease_circle.html index c553c72..7870cc6 100644 --- a/chapter_09/10_ease_circle.html +++ b/chapter_09/10_ease_circle.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/11_ease_elastic.html b/chapter_09/11_ease_elastic.html index 6c25476..df61bc2 100644 --- a/chapter_09/11_ease_elastic.html +++ b/chapter_09/11_ease_elastic.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/12_ease_bounce.html b/chapter_09/12_ease_bounce.html index c9ea3ef..e81aedd 100644 --- a/chapter_09/12_ease_bounce.html +++ b/chapter_09/12_ease_bounce.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/13_delay_static.html b/chapter_09/13_delay_static.html index 287a7c1..7334fae 100644 --- a/chapter_09/13_delay_static.html +++ b/chapter_09/13_delay_static.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/14_delay_dynamic.html b/chapter_09/14_delay_dynamic.html index bd8cd4f..5b247d3 100644 --- a/chapter_09/14_delay_dynamic.html +++ b/chapter_09/14_delay_dynamic.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/15_delay_dynamic_scaled.html b/chapter_09/15_delay_dynamic_scaled.html index 97b47c2..542018d 100644 --- a/chapter_09/15_delay_dynamic_scaled.html +++ b/chapter_09/15_delay_dynamic_scaled.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/16_delay_dynamic_scaled_fewer.html b/chapter_09/16_delay_dynamic_scaled_fewer.html index 6ee7eb3..c9d1a02 100644 --- a/chapter_09/16_delay_dynamic_scaled_fewer.html +++ b/chapter_09/16_delay_dynamic_scaled_fewer.html @@ -22,7 +22,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/17_randomized_data.html b/chapter_09/17_randomized_data.html index 28a3b8b..df2c01e 100644 --- a/chapter_09/17_randomized_data.html +++ b/chapter_09/17_randomized_data.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/18_dynamic_scale.html b/chapter_09/18_dynamic_scale.html index 310d82f..2ed2726 100644 --- a/chapter_09/18_dynamic_scale.html +++ b/chapter_09/18_dynamic_scale.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/25_adding_values.html b/chapter_09/25_adding_values.html index 2d01f35..6a74a49 100644 --- a/chapter_09/25_adding_values.html +++ b/chapter_09/25_adding_values.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/26_removing_values.html b/chapter_09/26_removing_values.html index 56905fd..fa605ad 100644 --- a/chapter_09/26_removing_values.html +++ b/chapter_09/26_removing_values.html @@ -23,7 +23,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/27_data_join_with_key.html b/chapter_09/27_data_join_with_key.html index 2e5f004..e48ff70 100644 --- a/chapter_09/27_data_join_with_key.html +++ b/chapter_09/27_data_join_with_key.html @@ -41,7 +41,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/28_adding_and_removing.html b/chapter_09/28_adding_and_removing.html index d94c149..839d4e9 100644 --- a/chapter_09/28_adding_and_removing.html +++ b/chapter_09/28_adding_and_removing.html @@ -42,7 +42,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_09/29_dynamic_labels.html b/chapter_09/29_dynamic_labels.html index d2bca25..679de22 100644 --- a/chapter_09/29_dynamic_labels.html +++ b/chapter_09/29_dynamic_labels.html @@ -42,7 +42,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/01_start.html b/chapter_10/01_start.html index 8133c24..ea87d13 100644 --- a/chapter_10/01_start.html +++ b/chapter_10/01_start.html @@ -20,7 +20,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/02_click.html b/chapter_10/02_click.html index c6a6b71..189e523 100644 --- a/chapter_10/02_click.html +++ b/chapter_10/02_click.html @@ -20,7 +20,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/03_hover.html b/chapter_10/03_hover.html index c790223..63bebac 100644 --- a/chapter_10/03_hover.html +++ b/chapter_10/03_hover.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/04_mouseover.html b/chapter_10/04_mouseover.html index eb4f530..ff93f08 100644 --- a/chapter_10/04_mouseover.html +++ b/chapter_10/04_mouseover.html @@ -20,7 +20,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/05_mouseout.html b/chapter_10/05_mouseout.html index 266af56..24982d6 100644 --- a/chapter_10/05_mouseout.html +++ b/chapter_10/05_mouseout.html @@ -20,7 +20,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/06_smoother.html b/chapter_10/06_smoother.html index f27ce10..bc2d711 100644 --- a/chapter_10/06_smoother.html +++ b/chapter_10/06_smoother.html @@ -20,7 +20,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/07_sort.html b/chapter_10/07_sort.html index a36447c..38e47e9 100644 --- a/chapter_10/07_sort.html +++ b/chapter_10/07_sort.html @@ -20,7 +20,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/08_sort_hover.html b/chapter_10/08_sort_hover.html index 95ff9ae..72d7c4e 100644 --- a/chapter_10/08_sort_hover.html +++ b/chapter_10/08_sort_hover.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/09_resort.html b/chapter_10/09_resort.html index 1d53b06..840e0d8 100644 --- a/chapter_10/09_resort.html +++ b/chapter_10/09_resort.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/10_delay.html b/chapter_10/10_delay.html index 9227bc5..a3fb5ed 100644 --- a/chapter_10/10_delay.html +++ b/chapter_10/10_delay.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/11_browser_tooltip.html b/chapter_10/11_browser_tooltip.html index 69edfcd..a3c4a3b 100644 --- a/chapter_10/11_browser_tooltip.html +++ b/chapter_10/11_browser_tooltip.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/12_browser_tooltip_text.html b/chapter_10/12_browser_tooltip_text.html index cb2996b..8d63127 100644 --- a/chapter_10/12_browser_tooltip_text.html +++ b/chapter_10/12_browser_tooltip_text.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/13_svg_tooltip.html b/chapter_10/13_svg_tooltip.html index 4a1a51d..dda119d 100644 --- a/chapter_10/13_svg_tooltip.html +++ b/chapter_10/13_svg_tooltip.html @@ -24,7 +24,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() diff --git a/chapter_10/14_div_tooltip.html b/chapter_10/14_div_tooltip.html index b1b7e2a..b1c0d5e 100644 --- a/chapter_10/14_div_tooltip.html +++ b/chapter_10/14_div_tooltip.html @@ -54,7 +54,7 @@ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) - .range([0, w]) + .rangeRound([0, w]) .paddingInner(0.05); var yScale = d3.scaleLinear() From 384118fbebf720c8e660c87fbb20af6f66cc9b76 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 3 Feb 2017 22:16:24 -0800 Subject: [PATCH 18/85] Comment clarifications --- chapter_09/25_adding_values.html | 2 +- chapter_09/26_removing_values.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chapter_09/25_adding_values.html b/chapter_09/25_adding_values.html index 6a74a49..51a7f81 100644 --- a/chapter_09/25_adding_values.html +++ b/chapter_09/25_adding_values.html @@ -109,7 +109,7 @@ .attr("fill", function(d) { //Sets the fill value return "rgb(0, 0, " + (d * 10) + ")"; }) - .merge(bars) //Update… + .merge(bars) //Merges the enter selection with the update selection .transition() //Initiate a transition on all elements in the update selection (all rects) .duration(500) .attr("x", function(d, i) { //Set new x position, based on the updated xScale diff --git a/chapter_09/26_removing_values.html b/chapter_09/26_removing_values.html index fa605ad..957601f 100644 --- a/chapter_09/26_removing_values.html +++ b/chapter_09/26_removing_values.html @@ -107,7 +107,7 @@ .attr("fill", function(d) { //Sets the fill value return "rgb(0, 0, " + (d * 10) + ")"; }) - .merge(bars) //Update… + .merge(bars) //Merges the enter selection with the update selection .transition() //Initiate a transition on all elements in the update selection (all rects) .duration(500) .attr("x", function(d, i) { //Set new x position, based on the updated xScale From 9934636d20ff6fab6ed17b7c3bae24b430df1dfd Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sat, 4 Feb 2017 16:47:42 -0800 Subject: [PATCH 19/85] rename and adding title tags --- chapter_11/01_pie.html | 2 +- chapter_11/{02_ring.html => 02_doughnut.html} | 2 +- chapter_11/03_stacked_bar.html | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) rename chapter_11/{02_ring.html => 02_doughnut.html} (96%) diff --git a/chapter_11/01_pie.html b/chapter_11/01_pie.html index 7206b9e..8d07777 100644 --- a/chapter_11/01_pie.html +++ b/chapter_11/01_pie.html @@ -2,7 +2,7 @@ - D3: Pie layout + D3: Pie layout pie chart + + + + + \ No newline at end of file diff --git a/chapter_11/05_stacked_bar_anchored.html b/chapter_11/05_stacked_bar_anchored.html new file mode 100644 index 0000000..5678c56 --- /dev/null +++ b/chapter_11/05_stacked_bar_anchored.html @@ -0,0 +1,85 @@ + + + + + D3: Stack layout stacked bar chart, anchored at bottom + + + + + + + \ No newline at end of file diff --git a/chapter_11/04_force_basic.html b/chapter_11/z04_force_basic.html similarity index 100% rename from chapter_11/04_force_basic.html rename to chapter_11/z04_force_basic.html diff --git a/chapter_11/04_force_draggable.html b/chapter_11/z05_force_draggable.html similarity index 100% rename from chapter_11/04_force_draggable.html rename to chapter_11/z05_force_draggable.html From fb9c7266c157aeaac8166de9f3aae60cd7909469 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 7 Feb 2017 14:38:38 -0800 Subject: [PATCH 22/85] Done with stack layout --- chapter_11/04_stacked_bar_reordered.html | 2 +- chapter_11/05_stacked_bar_anchored.html | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/chapter_11/04_stacked_bar_reordered.html b/chapter_11/04_stacked_bar_reordered.html index 5c22fff..a798a81 100644 --- a/chapter_11/04_stacked_bar_reordered.html +++ b/chapter_11/04_stacked_bar_reordered.html @@ -27,7 +27,7 @@ //Set up stack method var stack = d3.stack() .keys([ "apples", "oranges", "grapes" ]) - .order(d3.stackOrderDescending); // <-- flipped stacking order + .order(d3.stackOrderDescending); // <-- Flipped stacking order // Also try: // d3.stackOrderNone (the default, uses the order in which keys are specified) diff --git a/chapter_11/05_stacked_bar_anchored.html b/chapter_11/05_stacked_bar_anchored.html index 5678c56..3291a9f 100644 --- a/chapter_11/05_stacked_bar_anchored.html +++ b/chapter_11/05_stacked_bar_anchored.html @@ -27,7 +27,7 @@ //Set up stack method var stack = d3.stack() .keys([ "apples", "oranges", "grapes" ]) - .order(d3.stackOrderDescending); // <-- flipped stacking order + .order(d3.stackOrderDescending); // <-- Flipped stacking order //Data, stacked var series = stack(dataset); @@ -44,7 +44,7 @@ return d.apples + d.oranges + d.grapes; }) ]) - .range([h, 0]); // <-- flipped vertical scale + .range([h, 0]); // <-- Flipped vertical scale //Easy colors accessible via a 10-step ordinal scale var colors = d3.scaleOrdinal(d3.schemeCategory10); @@ -73,10 +73,10 @@ return xScale(i); }) .attr("y", function(d) { - return yScale(d[1]); // <-- changed y value + return yScale(d[1]); // <-- Changed y value }) .attr("height", function(d) { - return yScale(d[0]) - yScale(d[1]); // <-- changed height value + return yScale(d[0]) - yScale(d[1]); // <-- Changed height value }) .attr("width", xScale.bandwidth()); From 0f4180c4a6efb389b7a013741bae701a5af6e462 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 7 Feb 2017 22:11:41 -0800 Subject: [PATCH 23/85] Force layout example tweaks --- chapter_11/{z04_force_basic.html => 06_force.html} | 9 ++++----- ...{z05_force_draggable.html => 07_force_draggable.html} | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) rename chapter_11/{z04_force_basic.html => 06_force.html} (90%) rename chapter_11/{z05_force_draggable.html => 07_force_draggable.html} (92%) diff --git a/chapter_11/z04_force_basic.html b/chapter_11/06_force.html similarity index 90% rename from chapter_11/z04_force_basic.html rename to chapter_11/06_force.html index 006a91c..3dedb8a 100644 --- a/chapter_11/z04_force_basic.html +++ b/chapter_11/06_force.html @@ -46,12 +46,11 @@ ] }; - //Initialize a default force layout, using the nodes and edges in dataset + //Initialize a simple force layout, using the nodes and edges in dataset var force = d3.forceSimulation(dataset.nodes) - .force("charge", d3.forceManyBody()) - .force("link", d3.forceLink(dataset.edges)) - .force("center", d3.forceCenter().x(w/2).y(h/2)); - + .force("charge", d3.forceManyBody()) + .force("link", d3.forceLink(dataset.edges)) + .force("center", d3.forceCenter().x(w/2).y(h/2)); var colors = d3.scaleOrdinal(d3.schemeCategory10); diff --git a/chapter_11/z05_force_draggable.html b/chapter_11/07_force_draggable.html similarity index 92% rename from chapter_11/z05_force_draggable.html rename to chapter_11/07_force_draggable.html index 2a292f5..9635ea7 100644 --- a/chapter_11/z05_force_draggable.html +++ b/chapter_11/07_force_draggable.html @@ -46,12 +46,11 @@ ] }; - //Initialize a default force layout, using the nodes and edges in dataset + //Initialize a simple force layout, using the nodes and edges in dataset var force = d3.forceSimulation(dataset.nodes) - .force("charge", d3.forceManyBody()) - .force("link", d3.forceLink(dataset.edges)) - .force("center", d3.forceCenter().x(w/2).y(h/2)); - + .force("charge", d3.forceManyBody()) + .force("link", d3.forceLink(dataset.edges)) + .force("center", d3.forceCenter().x(w/2).y(h/2)); var colors = d3.scaleOrdinal(d3.schemeCategory10); From 67cbb4da2bb7ef6dd7011266d56c6c22d9b88d42 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 8 Feb 2017 13:04:56 -0800 Subject: [PATCH 24/85] Code updates for ch 12 --- chapter_12/01_paths.html | 3 ++- chapter_12/02_projection.html | 4 ++-- chapter_12/03_scaled.html | 6 +++--- chapter_12/05_choropleth.html | 3 ++- chapter_12/08_oceans.html | 4 ++-- chapter_12/README.md | 10 ++++++++-- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/chapter_12/01_paths.html b/chapter_12/01_paths.html index eef4e2d..2c714c9 100644 --- a/chapter_12/01_paths.html +++ b/chapter_12/01_paths.html @@ -16,7 +16,8 @@ var h = 300; //Define path generator, using the Albers USA projection - var path = d3.geoPath(d3.geoAlbersUsa()); + var path = d3.geoPath() + .projection(d3.geoAlbersUsa()); //Create SVG element var svg = d3.select("body") diff --git a/chapter_12/02_projection.html b/chapter_12/02_projection.html index 0ef7077..5f55214 100644 --- a/chapter_12/02_projection.html +++ b/chapter_12/02_projection.html @@ -17,11 +17,11 @@ //Define map projection var projection = d3.geoAlbersUsa() - .translate([w/2, h/2]); + .translate([w/2, h/2]); //Define path generator var path = d3.geoPath() - .projection(projection); + .projection(projection); //Create SVG element var svg = d3.select("body") diff --git a/chapter_12/03_scaled.html b/chapter_12/03_scaled.html index 30ca78e..8e2c73e 100644 --- a/chapter_12/03_scaled.html +++ b/chapter_12/03_scaled.html @@ -2,7 +2,7 @@ - D3: Scaling the AlbersUSA projection + D3: Scaling the Albers USA projection + + + + + \ No newline at end of file diff --git a/chapter_07/09_time_scale.html b/chapter_07/09_time_scale.html new file mode 100644 index 0000000..137ab18 --- /dev/null +++ b/chapter_07/09_time_scale.html @@ -0,0 +1,97 @@ + + + + + D3: Time scale + + + + + + + \ No newline at end of file diff --git a/chapter_07/time_scale_data.csv b/chapter_07/time_scale_data.csv new file mode 100644 index 0000000..180e128 --- /dev/null +++ b/chapter_07/time_scale_data.csv @@ -0,0 +1,32 @@ +Date,Amount +01/01/17,35 +01/02/17,30 +01/03/17,24 +01/04/17,37 +01/05/17,54 +01/06/17,55 +01/07/17,62 +01/08/17,62 +01/09/17,70 +01/10/17,66 +01/11/17,51 +01/12/17,63 +01/13/17,74 +01/14/17,58 +01/15/17,69 +01/16/17,56 +01/17/17,56 +01/18/17,50 +01/19/17,52 +01/20/17,48 +01/21/17,55 +01/22/17,44 +01/23/17,35 +01/24/17,32 +01/25/17,35 +01/26/17,21 +01/27/17,15 +01/28/17,32 +01/29/17,21 +01/30/17,12 +01/31/17,23 \ No newline at end of file From b526acc88f6f9a11d650964c830427c2fa6627c0 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 22 Feb 2017 15:30:21 -0800 Subject: [PATCH 31/85] Scatterplot code updates, using sqrt --- chapter_07/02_scaled_plot.html | 2 ++ chapter_07/03_scaled_plot_inverted.html | 2 ++ chapter_07/04_scaled_plot_padding.html | 2 ++ chapter_07/05_scaled_plot_radii.html | 2 ++ chapter_07/06_scaled_plot_big.html | 2 ++ chapter_07/07_scaled_plot_large.html | 2 ++ chapter_07/08_scaled_plot_sqrt_scale.html | 2 ++ chapter_08/01_axes.html | 6 +++--- chapter_08/02_axes_bottom.html | 4 ++-- chapter_08/03_axes_clean.html | 4 ++-- chapter_08/04_axes_y.html | 4 ++-- chapter_08/05_axes_random.html | 4 ++-- chapter_08/06_axes_no_labels.html | 4 ++-- chapter_08/07_axes_format.html | 4 ++-- 14 files changed, 29 insertions(+), 15 deletions(-) diff --git a/chapter_07/02_scaled_plot.html b/chapter_07/02_scaled_plot.html index 145b580..3130e79 100644 --- a/chapter_07/02_scaled_plot.html +++ b/chapter_07/02_scaled_plot.html @@ -35,6 +35,7 @@ .attr("width", w) .attr("height", h); + //Create circles svg.selectAll("circle") .data(dataset) .enter() @@ -49,6 +50,7 @@ return Math.sqrt(h - d[1]); }); + //Create labels svg.selectAll("text") .data(dataset) .enter() diff --git a/chapter_07/03_scaled_plot_inverted.html b/chapter_07/03_scaled_plot_inverted.html index e6febe4..2ad7fb3 100644 --- a/chapter_07/03_scaled_plot_inverted.html +++ b/chapter_07/03_scaled_plot_inverted.html @@ -35,6 +35,7 @@ .attr("width", w) .attr("height", h); + //Create circles svg.selectAll("circle") .data(dataset) .enter() @@ -49,6 +50,7 @@ return Math.sqrt(h - d[1]); }); + //Create labels svg.selectAll("text") .data(dataset) .enter() diff --git a/chapter_07/04_scaled_plot_padding.html b/chapter_07/04_scaled_plot_padding.html index f08d344..1180657 100644 --- a/chapter_07/04_scaled_plot_padding.html +++ b/chapter_07/04_scaled_plot_padding.html @@ -36,6 +36,7 @@ .attr("width", w) .attr("height", h); + //Create circles svg.selectAll("circle") .data(dataset) .enter() @@ -50,6 +51,7 @@ return Math.sqrt(h - d[1]); }); + //Create labels svg.selectAll("text") .data(dataset) .enter() diff --git a/chapter_07/05_scaled_plot_radii.html b/chapter_07/05_scaled_plot_radii.html index 6b279d2..d98054c 100644 --- a/chapter_07/05_scaled_plot_radii.html +++ b/chapter_07/05_scaled_plot_radii.html @@ -40,6 +40,7 @@ .attr("width", w) .attr("height", h); + //Create circles svg.selectAll("circle") .data(dataset) .enter() @@ -54,6 +55,7 @@ return rScale(d[1]); }); + //Create labels svg.selectAll("text") .data(dataset) .enter() diff --git a/chapter_07/06_scaled_plot_big.html b/chapter_07/06_scaled_plot_big.html index d4f3408..11b55a2 100644 --- a/chapter_07/06_scaled_plot_big.html +++ b/chapter_07/06_scaled_plot_big.html @@ -41,6 +41,7 @@ .attr("width", w) .attr("height", h); + //Create circles svg.selectAll("circle") .data(dataset) .enter() @@ -55,6 +56,7 @@ return rScale(d[1]); }); + //Create labels svg.selectAll("text") .data(dataset) .enter() diff --git a/chapter_07/07_scaled_plot_large.html b/chapter_07/07_scaled_plot_large.html index 67eaaeb..e70bb0a 100644 --- a/chapter_07/07_scaled_plot_large.html +++ b/chapter_07/07_scaled_plot_large.html @@ -41,6 +41,7 @@ .attr("width", w) .attr("height", h); + //Create circles svg.selectAll("circle") .data(dataset) .enter() @@ -55,6 +56,7 @@ return rScale(d[1]); }); + //Create labels svg.selectAll("text") .data(dataset) .enter() diff --git a/chapter_07/08_scaled_plot_sqrt_scale.html b/chapter_07/08_scaled_plot_sqrt_scale.html index a6a6192..32e26c0 100644 --- a/chapter_07/08_scaled_plot_sqrt_scale.html +++ b/chapter_07/08_scaled_plot_sqrt_scale.html @@ -41,6 +41,7 @@ .attr("width", w) .attr("height", h); + //Create circles svg.selectAll("circle") .data(dataset) .enter() @@ -55,6 +56,7 @@ return rScale(d[1]); }); + //Create labels svg.selectAll("text") .data(dataset) .enter() diff --git a/chapter_08/01_axes.html b/chapter_08/01_axes.html index 68f76e4..7729dbd 100644 --- a/chapter_08/01_axes.html +++ b/chapter_08/01_axes.html @@ -31,13 +31,13 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleLinear() + var rScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) - .range([2, 5]); + .range([0, 10]); //Define X axis var xAxis = d3.axisBottom() - .scale(xScale); + .scale(xScale); //Create SVG element var svg = d3.select("body") diff --git a/chapter_08/02_axes_bottom.html b/chapter_08/02_axes_bottom.html index b0f493a..caf8c30 100644 --- a/chapter_08/02_axes_bottom.html +++ b/chapter_08/02_axes_bottom.html @@ -31,9 +31,9 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleLinear() + var rScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) - .range([2, 5]); + .range([0, 10]); //Define X axis var xAxis = d3.axisBottom() diff --git a/chapter_08/03_axes_clean.html b/chapter_08/03_axes_clean.html index 7497482..6a7ef47 100644 --- a/chapter_08/03_axes_clean.html +++ b/chapter_08/03_axes_clean.html @@ -31,9 +31,9 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleLinear() + var rScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) - .range([2, 5]); + .range([0, 10]); //Define X axis var xAxis = d3.axisBottom() diff --git a/chapter_08/04_axes_y.html b/chapter_08/04_axes_y.html index d9d6f71..0d2d94c 100644 --- a/chapter_08/04_axes_y.html +++ b/chapter_08/04_axes_y.html @@ -31,9 +31,9 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleLinear() + var rScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) - .range([2, 5]); + .range([0, 10]); //Define X axis var xAxis = d3.axisBottom() diff --git a/chapter_08/05_axes_random.html b/chapter_08/05_axes_random.html index 492d9f3..450285b 100644 --- a/chapter_08/05_axes_random.html +++ b/chapter_08/05_axes_random.html @@ -45,9 +45,9 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleLinear() + var rScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) - .range([2, 5]); + .range([0, 10]); //Define X axis var xAxis = d3.axisBottom() diff --git a/chapter_08/06_axes_no_labels.html b/chapter_08/06_axes_no_labels.html index b26a9f5..dc21011 100644 --- a/chapter_08/06_axes_no_labels.html +++ b/chapter_08/06_axes_no_labels.html @@ -45,9 +45,9 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleLinear() + var rScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) - .range([2, 5]); + .range([0, 10]); //Define X axis var xAxis = d3.axisBottom() diff --git a/chapter_08/07_axes_format.html b/chapter_08/07_axes_format.html index fb8b042..38eed3b 100644 --- a/chapter_08/07_axes_format.html +++ b/chapter_08/07_axes_format.html @@ -45,9 +45,9 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleLinear() + var rScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) - .range([2, 5]); + .range([0, 10]); var formatAsPercentage = d3.format(".1%"); From fbe5aad2e4d65b160cc4d9354c083a08a71b80df Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 22 Feb 2017 16:26:06 -0800 Subject: [PATCH 32/85] New time axis examples --- chapter_08/08_time_axis.html | 119 ++++++++++++++++++++++++ chapter_08/09_time_axis_prettier.html | 124 ++++++++++++++++++++++++++ chapter_08/time_scale_data.csv | 32 +++++++ 3 files changed, 275 insertions(+) create mode 100644 chapter_08/08_time_axis.html create mode 100644 chapter_08/09_time_axis_prettier.html create mode 100644 chapter_08/time_scale_data.csv diff --git a/chapter_08/08_time_axis.html b/chapter_08/08_time_axis.html new file mode 100644 index 0000000..88971f9 --- /dev/null +++ b/chapter_08/08_time_axis.html @@ -0,0 +1,119 @@ + + + + + D3: Time axis + + + + + + + \ No newline at end of file diff --git a/chapter_08/09_time_axis_prettier.html b/chapter_08/09_time_axis_prettier.html new file mode 100644 index 0000000..3120878 --- /dev/null +++ b/chapter_08/09_time_axis_prettier.html @@ -0,0 +1,124 @@ + + + + + D3: Time axis, prettier + + + + + + + \ No newline at end of file diff --git a/chapter_08/time_scale_data.csv b/chapter_08/time_scale_data.csv new file mode 100644 index 0000000..180e128 --- /dev/null +++ b/chapter_08/time_scale_data.csv @@ -0,0 +1,32 @@ +Date,Amount +01/01/17,35 +01/02/17,30 +01/03/17,24 +01/04/17,37 +01/05/17,54 +01/06/17,55 +01/07/17,62 +01/08/17,62 +01/09/17,70 +01/10/17,66 +01/11/17,51 +01/12/17,63 +01/13/17,74 +01/14/17,58 +01/15/17,69 +01/16/17,56 +01/17/17,56 +01/18/17,50 +01/19/17,52 +01/20/17,48 +01/21/17,55 +01/22/17,44 +01/23/17,35 +01/24/17,32 +01/25/17,35 +01/26/17,21 +01/27/17,15 +01/28/17,32 +01/29/17,21 +01/30/17,12 +01/31/17,23 \ No newline at end of file From 9a81ef418dcb6c4fd92373256c5eb4af9116891e Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 24 Feb 2017 16:37:03 -0800 Subject: [PATCH 33/85] Rename chapters to make room for new examples --- {chapter_11 => chapter_13}/01_pie.html | 0 {chapter_11 => chapter_13}/02_doughnut.html | 0 {chapter_11 => chapter_13}/03_stacked_bar.html | 0 {chapter_11 => chapter_13}/04_stacked_bar_reordered.html | 0 {chapter_11 => chapter_13}/05_stacked_bar_anchored.html | 0 {chapter_11 => chapter_13}/06_force.html | 0 {chapter_11 => chapter_13}/07_force_draggable.html | 0 {chapter_12 => chapter_14}/01_paths.html | 0 {chapter_12 => chapter_14}/02_projection.html | 0 {chapter_12 => chapter_14}/03_scaled.html | 0 {chapter_12 => chapter_14}/04_fill.html | 0 {chapter_12 => chapter_14}/05_choropleth.html | 0 {chapter_12 => chapter_14}/06_points.html | 0 {chapter_12 => chapter_14}/07_points_sized.html | 0 {chapter_12 => chapter_14}/08_oceans.html | 0 {chapter_12 => chapter_14}/09_mercator.html | 0 {chapter_12 => chapter_14}/README.md | 0 {chapter_12 => chapter_14}/oceans.json | 0 {chapter_12 => chapter_14}/us-ag-productivity-2004.csv | 0 {chapter_12 => chapter_14}/us-cities.csv | 0 {chapter_12 => chapter_14}/us-states.json | 0 21 files changed, 0 insertions(+), 0 deletions(-) rename {chapter_11 => chapter_13}/01_pie.html (100%) rename {chapter_11 => chapter_13}/02_doughnut.html (100%) rename {chapter_11 => chapter_13}/03_stacked_bar.html (100%) rename {chapter_11 => chapter_13}/04_stacked_bar_reordered.html (100%) rename {chapter_11 => chapter_13}/05_stacked_bar_anchored.html (100%) rename {chapter_11 => chapter_13}/06_force.html (100%) rename {chapter_11 => chapter_13}/07_force_draggable.html (100%) rename {chapter_12 => chapter_14}/01_paths.html (100%) rename {chapter_12 => chapter_14}/02_projection.html (100%) rename {chapter_12 => chapter_14}/03_scaled.html (100%) rename {chapter_12 => chapter_14}/04_fill.html (100%) rename {chapter_12 => chapter_14}/05_choropleth.html (100%) rename {chapter_12 => chapter_14}/06_points.html (100%) rename {chapter_12 => chapter_14}/07_points_sized.html (100%) rename {chapter_12 => chapter_14}/08_oceans.html (100%) rename {chapter_12 => chapter_14}/09_mercator.html (100%) rename {chapter_12 => chapter_14}/README.md (100%) rename {chapter_12 => chapter_14}/oceans.json (100%) rename {chapter_12 => chapter_14}/us-ag-productivity-2004.csv (100%) rename {chapter_12 => chapter_14}/us-cities.csv (100%) rename {chapter_12 => chapter_14}/us-states.json (100%) diff --git a/chapter_11/01_pie.html b/chapter_13/01_pie.html similarity index 100% rename from chapter_11/01_pie.html rename to chapter_13/01_pie.html diff --git a/chapter_11/02_doughnut.html b/chapter_13/02_doughnut.html similarity index 100% rename from chapter_11/02_doughnut.html rename to chapter_13/02_doughnut.html diff --git a/chapter_11/03_stacked_bar.html b/chapter_13/03_stacked_bar.html similarity index 100% rename from chapter_11/03_stacked_bar.html rename to chapter_13/03_stacked_bar.html diff --git a/chapter_11/04_stacked_bar_reordered.html b/chapter_13/04_stacked_bar_reordered.html similarity index 100% rename from chapter_11/04_stacked_bar_reordered.html rename to chapter_13/04_stacked_bar_reordered.html diff --git a/chapter_11/05_stacked_bar_anchored.html b/chapter_13/05_stacked_bar_anchored.html similarity index 100% rename from chapter_11/05_stacked_bar_anchored.html rename to chapter_13/05_stacked_bar_anchored.html diff --git a/chapter_11/06_force.html b/chapter_13/06_force.html similarity index 100% rename from chapter_11/06_force.html rename to chapter_13/06_force.html diff --git a/chapter_11/07_force_draggable.html b/chapter_13/07_force_draggable.html similarity index 100% rename from chapter_11/07_force_draggable.html rename to chapter_13/07_force_draggable.html diff --git a/chapter_12/01_paths.html b/chapter_14/01_paths.html similarity index 100% rename from chapter_12/01_paths.html rename to chapter_14/01_paths.html diff --git a/chapter_12/02_projection.html b/chapter_14/02_projection.html similarity index 100% rename from chapter_12/02_projection.html rename to chapter_14/02_projection.html diff --git a/chapter_12/03_scaled.html b/chapter_14/03_scaled.html similarity index 100% rename from chapter_12/03_scaled.html rename to chapter_14/03_scaled.html diff --git a/chapter_12/04_fill.html b/chapter_14/04_fill.html similarity index 100% rename from chapter_12/04_fill.html rename to chapter_14/04_fill.html diff --git a/chapter_12/05_choropleth.html b/chapter_14/05_choropleth.html similarity index 100% rename from chapter_12/05_choropleth.html rename to chapter_14/05_choropleth.html diff --git a/chapter_12/06_points.html b/chapter_14/06_points.html similarity index 100% rename from chapter_12/06_points.html rename to chapter_14/06_points.html diff --git a/chapter_12/07_points_sized.html b/chapter_14/07_points_sized.html similarity index 100% rename from chapter_12/07_points_sized.html rename to chapter_14/07_points_sized.html diff --git a/chapter_12/08_oceans.html b/chapter_14/08_oceans.html similarity index 100% rename from chapter_12/08_oceans.html rename to chapter_14/08_oceans.html diff --git a/chapter_12/09_mercator.html b/chapter_14/09_mercator.html similarity index 100% rename from chapter_12/09_mercator.html rename to chapter_14/09_mercator.html diff --git a/chapter_12/README.md b/chapter_14/README.md similarity index 100% rename from chapter_12/README.md rename to chapter_14/README.md diff --git a/chapter_12/oceans.json b/chapter_14/oceans.json similarity index 100% rename from chapter_12/oceans.json rename to chapter_14/oceans.json diff --git a/chapter_12/us-ag-productivity-2004.csv b/chapter_14/us-ag-productivity-2004.csv similarity index 100% rename from chapter_12/us-ag-productivity-2004.csv rename to chapter_14/us-ag-productivity-2004.csv diff --git a/chapter_12/us-cities.csv b/chapter_14/us-cities.csv similarity index 100% rename from chapter_12/us-cities.csv rename to chapter_14/us-cities.csv diff --git a/chapter_12/us-states.json b/chapter_14/us-states.json similarity index 100% rename from chapter_12/us-states.json rename to chapter_14/us-states.json From ac8e01995fbe6fe70eeeaf92fd19e7c7a913b872 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 27 Feb 2017 14:55:21 -0800 Subject: [PATCH 34/85] Added data READMEs --- chapter_07/README.md | 6 ++++++ chapter_08/README.md | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 chapter_07/README.md create mode 100644 chapter_08/README.md diff --git a/chapter_07/README.md b/chapter_07/README.md new file mode 100644 index 0000000..390ada1 --- /dev/null +++ b/chapter_07/README.md @@ -0,0 +1,6 @@ + +### time_scale_data.csv + +This file consists of a daily time series, from January 1 through 31, 2017. The "Amount" value in each row is semi-random, and was generated by me, Scott Murray, using the Numbers spreadsheet application. + +You are welcome to use, reuse, adapt, and republish these random numbers in any context. They are about as useful as [Dilbert’s budget numbers](http://dilbert.com/strip/1999-04-27). \ No newline at end of file diff --git a/chapter_08/README.md b/chapter_08/README.md new file mode 100644 index 0000000..390ada1 --- /dev/null +++ b/chapter_08/README.md @@ -0,0 +1,6 @@ + +### time_scale_data.csv + +This file consists of a daily time series, from January 1 through 31, 2017. The "Amount" value in each row is semi-random, and was generated by me, Scott Murray, using the Numbers spreadsheet application. + +You are welcome to use, reuse, adapt, and republish these random numbers in any context. They are about as useful as [Dilbert’s budget numbers](http://dilbert.com/strip/1999-04-27). \ No newline at end of file From 07d867399ccd30ba256d7bec6cccf74fbff27e07 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 27 Feb 2017 15:49:20 -0800 Subject: [PATCH 35/85] Adding some ch 11 examples --- chapter_11/01_line_chart.html | 76 ++ chapter_11/02_line_chart_axes.html | 102 +++ chapter_11/README.md | 12 + chapter_11/mauna_loa_co2_monthly_averages.csv | 708 ++++++++++++++++++ 4 files changed, 898 insertions(+) create mode 100644 chapter_11/01_line_chart.html create mode 100644 chapter_11/02_line_chart_axes.html create mode 100644 chapter_11/README.md create mode 100644 chapter_11/mauna_loa_co2_monthly_averages.csv diff --git a/chapter_11/01_line_chart.html b/chapter_11/01_line_chart.html new file mode 100644 index 0000000..bdcd9ab --- /dev/null +++ b/chapter_11/01_line_chart.html @@ -0,0 +1,76 @@ + + + + + D3: Line chart + + + + + + + \ No newline at end of file diff --git a/chapter_11/02_line_chart_axes.html b/chapter_11/02_line_chart_axes.html new file mode 100644 index 0000000..755b7c5 --- /dev/null +++ b/chapter_11/02_line_chart_axes.html @@ -0,0 +1,102 @@ + + + + + D3: Line chart + + + + + + + \ No newline at end of file diff --git a/chapter_11/README.md b/chapter_11/README.md new file mode 100644 index 0000000..f5a78ff --- /dev/null +++ b/chapter_11/README.md @@ -0,0 +1,12 @@ + +### mauna_loa_co2_monthly_averages.csv + +This file was derived from data provided by the National Oceanic & Atmospheric Administration’s Earth System Research Laboratory, Dr. Pieter Tans, NOAA/ESRL (www.esrl.noaa.gov/gmd/ccgg/trends/) and Dr. Ralph Keeling, Scripps Institution of Oceanography (scrippsco2.ucsd.edu/). + +“Mauna Loa CO2 monthly mean data” +ftp://aftp.cmdl.noaa.gov/products/trends/co2/co2_mm_mlo.txt + +As accessed on February 27, 2017 from: +https://www.esrl.noaa.gov/gmd/ccgg/trends/data.html + +Data was cleaned and converted to CSV using [OpenRefine](http://openrefine.org). diff --git a/chapter_11/mauna_loa_co2_monthly_averages.csv b/chapter_11/mauna_loa_co2_monthly_averages.csv new file mode 100644 index 0000000..b1a3b7f --- /dev/null +++ b/chapter_11/mauna_loa_co2_monthly_averages.csv @@ -0,0 +1,708 @@ +year,month,average +1958,3,315.71 +1958,4,317.45 +1958,5,317.5 +1958,6,-99.99 +1958,7,315.86 +1958,8,314.93 +1958,9,313.2 +1958,10,-99.99 +1958,11,313.33 +1958,12,314.67 +1959,1,315.62 +1959,2,316.38 +1959,3,316.71 +1959,4,317.72 +1959,5,318.29 +1959,6,318.15 +1959,7,316.54 +1959,8,314.8 +1959,9,313.84 +1959,10,313.26 +1959,11,314.8 +1959,12,315.58 +1960,1,316.43 +1960,2,316.97 +1960,3,317.58 +1960,4,319.02 +1960,5,320.03 +1960,6,319.59 +1960,7,318.18 +1960,8,315.91 +1960,9,314.16 +1960,10,313.83 +1960,11,315.0 +1960,12,316.19 +1961,1,316.93 +1961,2,317.7 +1961,3,318.54 +1961,4,319.48 +1961,5,320.58 +1961,6,319.77 +1961,7,318.57 +1961,8,316.79 +1961,9,314.8 +1961,10,315.38 +1961,11,316.1 +1961,12,317.01 +1962,1,317.94 +1962,2,318.56 +1962,3,319.68 +1962,4,320.63 +1962,5,321.01 +1962,6,320.55 +1962,7,319.58 +1962,8,317.4 +1962,9,316.26 +1962,10,315.42 +1962,11,316.69 +1962,12,317.69 +1963,1,318.74 +1963,2,319.08 +1963,3,319.86 +1963,4,321.39 +1963,5,322.25 +1963,6,321.47 +1963,7,319.74 +1963,8,317.77 +1963,9,316.21 +1963,10,315.99 +1963,11,317.12 +1963,12,318.31 +1964,1,319.57 +1964,2,-99.99 +1964,3,-99.99 +1964,4,-99.99 +1964,5,322.25 +1964,6,321.89 +1964,7,320.44 +1964,8,318.7 +1964,9,316.7 +1964,10,316.79 +1964,11,317.79 +1964,12,318.71 +1965,1,319.44 +1965,2,320.44 +1965,3,320.89 +1965,4,322.13 +1965,5,322.16 +1965,6,321.87 +1965,7,321.39 +1965,8,318.81 +1965,9,317.81 +1965,10,317.3 +1965,11,318.87 +1965,12,319.42 +1966,1,320.62 +1966,2,321.59 +1966,3,322.39 +1966,4,323.87 +1966,5,324.01 +1966,6,323.75 +1966,7,322.39 +1966,8,320.37 +1966,9,318.64 +1966,10,318.1 +1966,11,319.79 +1966,12,321.08 +1967,1,322.07 +1967,2,322.5 +1967,3,323.04 +1967,4,324.42 +1967,5,325.0 +1967,6,324.09 +1967,7,322.55 +1967,8,320.92 +1967,9,319.31 +1967,10,319.31 +1967,11,320.72 +1967,12,321.96 +1968,1,322.57 +1968,2,323.15 +1968,3,323.89 +1968,4,325.02 +1968,5,325.57 +1968,6,325.36 +1968,7,324.14 +1968,8,322.03 +1968,9,320.41 +1968,10,320.25 +1968,11,321.31 +1968,12,322.84 +1969,1,324.0 +1969,2,324.42 +1969,3,325.64 +1969,4,326.66 +1969,5,327.34 +1969,6,326.76 +1969,7,325.88 +1969,8,323.67 +1969,9,322.38 +1969,10,321.78 +1969,11,322.85 +1969,12,324.11 +1970,1,325.03 +1970,2,325.99 +1970,3,326.87 +1970,4,328.13 +1970,5,328.07 +1970,6,327.66 +1970,7,326.35 +1970,8,324.69 +1970,9,323.1 +1970,10,323.16 +1970,11,323.98 +1970,12,325.13 +1971,1,326.17 +1971,2,326.68 +1971,3,327.18 +1971,4,327.78 +1971,5,328.92 +1971,6,328.57 +1971,7,327.34 +1971,8,325.46 +1971,9,323.36 +1971,10,323.57 +1971,11,324.8 +1971,12,326.01 +1972,1,326.77 +1972,2,327.63 +1972,3,327.75 +1972,4,329.72 +1972,5,330.07 +1972,6,329.09 +1972,7,328.05 +1972,8,326.32 +1972,9,324.93 +1972,10,325.06 +1972,11,326.5 +1972,12,327.55 +1973,1,328.54 +1973,2,329.56 +1973,3,330.3 +1973,4,331.5 +1973,5,332.48 +1973,6,332.07 +1973,7,330.87 +1973,8,329.31 +1973,9,327.51 +1973,10,327.18 +1973,11,328.16 +1973,12,328.64 +1974,1,329.35 +1974,2,330.71 +1974,3,331.48 +1974,4,332.65 +1974,5,333.2 +1974,6,332.16 +1974,7,331.07 +1974,8,329.12 +1974,9,327.32 +1974,10,327.28 +1974,11,328.3 +1974,12,329.58 +1975,1,330.73 +1975,2,331.46 +1975,3,331.9 +1975,4,333.17 +1975,5,333.94 +1975,6,333.45 +1975,7,331.98 +1975,8,329.95 +1975,9,328.5 +1975,10,328.35 +1975,11,329.37 +1975,12,-99.99 +1976,1,331.59 +1976,2,332.75 +1976,3,333.52 +1976,4,334.64 +1976,5,334.77 +1976,6,334.0 +1976,7,333.06 +1976,8,330.68 +1976,9,328.95 +1976,10,328.75 +1976,11,330.15 +1976,12,331.62 +1977,1,332.66 +1977,2,333.13 +1977,3,334.95 +1977,4,336.13 +1977,5,336.93 +1977,6,336.16 +1977,7,334.88 +1977,8,332.56 +1977,9,331.29 +1977,10,331.27 +1977,11,332.41 +1977,12,333.6 +1978,1,334.95 +1978,2,335.25 +1978,3,336.66 +1978,4,337.69 +1978,5,338.03 +1978,6,338.01 +1978,7,336.41 +1978,8,334.41 +1978,9,332.37 +1978,10,332.41 +1978,11,333.75 +1978,12,334.9 +1979,1,336.14 +1979,2,336.69 +1979,3,338.27 +1979,4,338.96 +1979,5,339.21 +1979,6,339.26 +1979,7,337.54 +1979,8,335.75 +1979,9,333.98 +1979,10,334.19 +1979,11,335.31 +1979,12,336.81 +1980,1,337.9 +1980,2,338.34 +1980,3,340.01 +1980,4,340.93 +1980,5,341.48 +1980,6,341.33 +1980,7,339.4 +1980,8,337.7 +1980,9,336.19 +1980,10,336.15 +1980,11,337.27 +1980,12,338.32 +1981,1,339.29 +1981,2,340.55 +1981,3,341.61 +1981,4,342.53 +1981,5,343.04 +1981,6,342.54 +1981,7,340.78 +1981,8,338.44 +1981,9,336.95 +1981,10,337.08 +1981,11,338.58 +1981,12,339.88 +1982,1,340.96 +1982,2,341.73 +1982,3,342.82 +1982,4,343.97 +1982,5,344.63 +1982,6,343.79 +1982,7,342.32 +1982,8,340.09 +1982,9,338.28 +1982,10,338.29 +1982,11,339.6 +1982,12,340.9 +1983,1,341.68 +1983,2,342.9 +1983,3,343.33 +1983,4,345.25 +1983,5,346.03 +1983,6,345.63 +1983,7,344.19 +1983,8,342.27 +1983,9,340.35 +1983,10,340.38 +1983,11,341.59 +1983,12,343.05 +1984,1,344.1 +1984,2,344.79 +1984,3,345.52 +1984,4,-99.99 +1984,5,347.63 +1984,6,346.97 +1984,7,345.53 +1984,8,343.55 +1984,9,341.4 +1984,10,341.67 +1984,11,343.1 +1984,12,344.7 +1985,1,345.21 +1985,2,346.16 +1985,3,347.74 +1985,4,348.34 +1985,5,349.06 +1985,6,348.38 +1985,7,346.72 +1985,8,345.02 +1985,9,343.27 +1985,10,343.13 +1985,11,344.49 +1985,12,345.88 +1986,1,346.56 +1986,2,347.28 +1986,3,348.01 +1986,4,349.77 +1986,5,350.38 +1986,6,349.93 +1986,7,348.16 +1986,8,346.08 +1986,9,345.22 +1986,10,344.51 +1986,11,345.93 +1986,12,347.22 +1987,1,348.52 +1987,2,348.73 +1987,3,349.73 +1987,4,351.31 +1987,5,352.09 +1987,6,351.53 +1987,7,350.11 +1987,8,348.08 +1987,9,346.52 +1987,10,346.59 +1987,11,347.96 +1987,12,349.16 +1988,1,350.39 +1988,2,351.64 +1988,3,352.41 +1988,4,353.69 +1988,5,354.21 +1988,6,353.72 +1988,7,352.69 +1988,8,350.4 +1988,9,348.92 +1988,10,349.13 +1988,11,350.2 +1988,12,351.41 +1989,1,352.91 +1989,2,353.27 +1989,3,353.96 +1989,4,355.64 +1989,5,355.86 +1989,6,355.37 +1989,7,353.99 +1989,8,351.81 +1989,9,350.05 +1989,10,350.25 +1989,11,351.49 +1989,12,352.85 +1990,1,353.8 +1990,2,355.04 +1990,3,355.73 +1990,4,356.32 +1990,5,357.32 +1990,6,356.34 +1990,7,354.84 +1990,8,353.01 +1990,9,351.31 +1990,10,351.62 +1990,11,353.07 +1990,12,354.33 +1991,1,354.84 +1991,2,355.73 +1991,3,357.23 +1991,4,358.66 +1991,5,359.13 +1991,6,358.13 +1991,7,356.19 +1991,8,353.85 +1991,9,352.25 +1991,10,352.35 +1991,11,353.81 +1991,12,355.12 +1992,1,356.25 +1992,2,357.11 +1992,3,357.86 +1992,4,359.09 +1992,5,359.59 +1992,6,359.33 +1992,7,357.01 +1992,8,354.94 +1992,9,352.95 +1992,10,353.32 +1992,11,354.32 +1992,12,355.57 +1993,1,357.0 +1993,2,357.31 +1993,3,358.47 +1993,4,359.27 +1993,5,360.19 +1993,6,359.52 +1993,7,357.33 +1993,8,355.64 +1993,9,354.03 +1993,10,354.12 +1993,11,355.41 +1993,12,356.91 +1994,1,358.24 +1994,2,358.92 +1994,3,359.99 +1994,4,361.23 +1994,5,361.65 +1994,6,360.81 +1994,7,359.38 +1994,8,357.46 +1994,9,355.73 +1994,10,356.07 +1994,11,357.53 +1994,12,358.98 +1995,1,359.92 +1995,2,360.86 +1995,3,361.83 +1995,4,363.3 +1995,5,363.69 +1995,6,363.19 +1995,7,361.64 +1995,8,359.12 +1995,9,358.17 +1995,10,357.99 +1995,11,359.45 +1995,12,360.68 +1996,1,362.07 +1996,2,363.24 +1996,3,364.17 +1996,4,364.57 +1996,5,365.13 +1996,6,364.92 +1996,7,363.55 +1996,8,361.38 +1996,9,359.54 +1996,10,359.58 +1996,11,360.89 +1996,12,362.24 +1997,1,363.09 +1997,2,364.03 +1997,3,364.51 +1997,4,366.35 +1997,5,366.64 +1997,6,365.59 +1997,7,364.31 +1997,8,362.25 +1997,9,360.29 +1997,10,360.82 +1997,11,362.49 +1997,12,364.38 +1998,1,365.26 +1998,2,365.98 +1998,3,367.24 +1998,4,368.66 +1998,5,369.42 +1998,6,368.99 +1998,7,367.82 +1998,8,365.95 +1998,9,364.02 +1998,10,364.4 +1998,11,365.52 +1998,12,367.13 +1999,1,368.18 +1999,2,369.07 +1999,3,369.68 +1999,4,370.99 +1999,5,370.96 +1999,6,370.3 +1999,7,369.45 +1999,8,366.9 +1999,9,364.81 +1999,10,365.37 +1999,11,366.72 +1999,12,368.1 +2000,1,369.29 +2000,2,369.55 +2000,3,370.6 +2000,4,371.81 +2000,5,371.58 +2000,6,371.7 +2000,7,369.86 +2000,8,368.13 +2000,9,367.0 +2000,10,367.03 +2000,11,368.37 +2000,12,369.67 +2001,1,370.59 +2001,2,371.51 +2001,3,372.43 +2001,4,373.37 +2001,5,373.85 +2001,6,373.21 +2001,7,371.51 +2001,8,369.61 +2001,9,368.18 +2001,10,368.45 +2001,11,369.76 +2001,12,371.24 +2002,1,372.53 +2002,2,373.2 +2002,3,374.12 +2002,4,375.02 +2002,5,375.76 +2002,6,375.52 +2002,7,374.01 +2002,8,371.85 +2002,9,370.75 +2002,10,370.55 +2002,11,372.25 +2002,12,373.79 +2003,1,374.88 +2003,2,375.64 +2003,3,376.45 +2003,4,377.73 +2003,5,378.6 +2003,6,378.28 +2003,7,376.7 +2003,8,374.38 +2003,9,373.17 +2003,10,373.14 +2003,11,374.66 +2003,12,375.99 +2004,1,377.0 +2004,2,377.87 +2004,3,378.88 +2004,4,380.35 +2004,5,380.62 +2004,6,379.69 +2004,7,377.47 +2004,8,376.01 +2004,9,374.25 +2004,10,374.46 +2004,11,376.16 +2004,12,377.51 +2005,1,378.46 +2005,2,379.73 +2005,3,380.77 +2005,4,382.29 +2005,5,382.45 +2005,6,382.22 +2005,7,380.74 +2005,8,378.74 +2005,9,376.7 +2005,10,377.0 +2005,11,378.35 +2005,12,380.11 +2006,1,381.38 +2006,2,382.2 +2006,3,382.67 +2006,4,384.61 +2006,5,385.03 +2006,6,384.05 +2006,7,382.46 +2006,8,380.41 +2006,9,378.85 +2006,10,379.13 +2006,11,380.15 +2006,12,381.82 +2007,1,382.89 +2007,2,383.9 +2007,3,384.58 +2007,4,386.5 +2007,5,386.56 +2007,6,386.1 +2007,7,384.5 +2007,8,381.99 +2007,9,380.96 +2007,10,381.12 +2007,11,382.45 +2007,12,383.94 +2008,1,385.52 +2008,2,385.82 +2008,3,386.03 +2008,4,387.21 +2008,5,388.54 +2008,6,387.76 +2008,7,386.36 +2008,8,384.09 +2008,9,383.18 +2008,10,382.99 +2008,11,384.19 +2008,12,385.56 +2009,1,386.94 +2009,2,387.48 +2009,3,388.82 +2009,4,389.55 +2009,5,390.14 +2009,6,389.48 +2009,7,388.03 +2009,8,386.11 +2009,9,384.74 +2009,10,384.43 +2009,11,386.02 +2009,12,387.42 +2010,1,388.71 +2010,2,390.2 +2010,3,391.17 +2010,4,392.46 +2010,5,393.0 +2010,6,392.15 +2010,7,390.2 +2010,8,388.35 +2010,9,386.85 +2010,10,387.24 +2010,11,388.67 +2010,12,389.79 +2011,1,391.33 +2011,2,391.86 +2011,3,392.6 +2011,4,393.25 +2011,5,394.19 +2011,6,393.73 +2011,7,392.51 +2011,8,390.13 +2011,9,389.08 +2011,10,389.0 +2011,11,390.28 +2011,12,391.86 +2012,1,393.12 +2012,2,393.86 +2012,3,394.4 +2012,4,396.18 +2012,5,396.74 +2012,6,395.71 +2012,7,394.36 +2012,8,392.39 +2012,9,391.11 +2012,10,391.05 +2012,11,392.98 +2012,12,394.34 +2013,1,395.55 +2013,2,396.8 +2013,3,397.43 +2013,4,398.41 +2013,5,399.78 +2013,6,398.61 +2013,7,397.32 +2013,8,395.2 +2013,9,393.45 +2013,10,393.7 +2013,11,395.16 +2013,12,396.84 +2014,1,397.85 +2014,2,398.01 +2014,3,399.77 +2014,4,401.38 +2014,5,401.78 +2014,6,401.25 +2014,7,399.1 +2014,8,397.03 +2014,9,395.38 +2014,10,396.03 +2014,11,397.28 +2014,12,398.91 +2015,1,399.98 +2015,2,400.28 +2015,3,401.54 +2015,4,403.28 +2015,5,403.96 +2015,6,402.8 +2015,7,401.31 +2015,8,398.93 +2015,9,397.63 +2015,10,398.29 +2015,11,400.16 +2015,12,401.85 +2016,1,402.52 +2016,2,404.04 +2016,3,404.83 +2016,4,407.42 +2016,5,407.7 +2016,6,406.81 +2016,7,404.39 +2016,8,402.25 +2016,9,401.03 +2016,10,401.57 +2016,11,403.53 +2016,12,404.48 +2017,1,406.13 From 563313de94987c413cfca48a8c5e3c1b2796a953 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 28 Feb 2017 11:47:00 -0800 Subject: [PATCH 36/85] More ch 11 examples --- chapter_11/02_line_chart_axes.html | 4 +- chapter_11/03_line_chart_missing.html | 103 ++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 chapter_11/03_line_chart_missing.html diff --git a/chapter_11/02_line_chart_axes.html b/chapter_11/02_line_chart_axes.html index 755b7c5..515af0a 100644 --- a/chapter_11/02_line_chart_axes.html +++ b/chapter_11/02_line_chart_axes.html @@ -2,7 +2,7 @@ - D3: Line chart + D3: Line chart with axes + + + + + \ No newline at end of file From f6e47f2f76875db6b525c6ad606afdaee9019905 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 28 Feb 2017 15:41:16 -0800 Subject: [PATCH 37/85] Line and area chart examples --- chapter_11/01_line_chart.html | 2 +- chapter_11/02_line_chart_axes.html | 2 +- chapter_11/03_line_chart_missing.html | 2 +- chapter_11/04_line_chart_adjusted.html | 119 +++++++++++++++++++ chapter_11/05_line_chart_labeled.html | 146 +++++++++++++++++++++++ chapter_11/06_area_chart.html | 153 +++++++++++++++++++++++++ 6 files changed, 421 insertions(+), 3 deletions(-) create mode 100644 chapter_11/04_line_chart_adjusted.html create mode 100644 chapter_11/05_line_chart_labeled.html create mode 100644 chapter_11/06_area_chart.html diff --git a/chapter_11/01_line_chart.html b/chapter_11/01_line_chart.html index bdcd9ab..0e36366 100644 --- a/chapter_11/01_line_chart.html +++ b/chapter_11/01_line_chart.html @@ -53,7 +53,7 @@ .range([h, 0]); //Define line generator - var line = d3.line() + line = d3.line() .x(function(d) { return xScale(d.date); }) .y(function(d) { return yScale(d.average); }); diff --git a/chapter_11/02_line_chart_axes.html b/chapter_11/02_line_chart_axes.html index 515af0a..84c5e72 100644 --- a/chapter_11/02_line_chart_axes.html +++ b/chapter_11/02_line_chart_axes.html @@ -67,7 +67,7 @@ .ticks(10); //Define line generator - var line = d3.line() + line = d3.line() .x(function(d) { return xScale(d.date); }) .y(function(d) { return yScale(d.average); }); diff --git a/chapter_11/03_line_chart_missing.html b/chapter_11/03_line_chart_missing.html index 3574765..016e6c6 100644 --- a/chapter_11/03_line_chart_missing.html +++ b/chapter_11/03_line_chart_missing.html @@ -67,7 +67,7 @@ .ticks(10); //Define line generator - var line = d3.line() + line = d3.line() .defined(function(d) { return d.average >= 0; }) .x(function(d) { return xScale(d.date); }) .y(function(d) { return yScale(d.average); }); diff --git a/chapter_11/04_line_chart_adjusted.html b/chapter_11/04_line_chart_adjusted.html new file mode 100644 index 0000000..229c3ac --- /dev/null +++ b/chapter_11/04_line_chart_adjusted.html @@ -0,0 +1,119 @@ + + + + + D3: Line chart, adjusted + + + + + + + \ No newline at end of file diff --git a/chapter_11/05_line_chart_labeled.html b/chapter_11/05_line_chart_labeled.html new file mode 100644 index 0000000..3ca10da --- /dev/null +++ b/chapter_11/05_line_chart_labeled.html @@ -0,0 +1,146 @@ + + + + + D3: Line chart, labeled + + + + + + + \ No newline at end of file diff --git a/chapter_11/06_area_chart.html b/chapter_11/06_area_chart.html new file mode 100644 index 0000000..f3333d3 --- /dev/null +++ b/chapter_11/06_area_chart.html @@ -0,0 +1,153 @@ + + + + + D3: Line chart, labeled + + + + + + + \ No newline at end of file From 735a8d79fb235362f328d56649ab42ae64c89282 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 1 Mar 2017 20:58:01 -0800 Subject: [PATCH 38/85] Ch 11 data citation update --- chapter_11/README.md | 4 ++- chapter_16/README.md | 85 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 chapter_16/README.md diff --git a/chapter_11/README.md b/chapter_11/README.md index f5a78ff..5f0adb0 100644 --- a/chapter_11/README.md +++ b/chapter_11/README.md @@ -4,9 +4,11 @@ This file was derived from data provided by the National Oceanic & Atmospheric Administration’s Earth System Research Laboratory, Dr. Pieter Tans, NOAA/ESRL (www.esrl.noaa.gov/gmd/ccgg/trends/) and Dr. Ralph Keeling, Scripps Institution of Oceanography (scrippsco2.ucsd.edu/). “Mauna Loa CO2 monthly mean data” -ftp://aftp.cmdl.noaa.gov/products/trends/co2/co2_mm_mlo.txt As accessed on February 27, 2017 from: +ftp://aftp.cmdl.noaa.gov/products/trends/co2/co2_mm_mlo.txt + +Source page and more info: https://www.esrl.noaa.gov/gmd/ccgg/trends/data.html Data was cleaned and converted to CSV using [OpenRefine](http://openrefine.org). diff --git a/chapter_16/README.md b/chapter_16/README.md new file mode 100644 index 0000000..715eae8 --- /dev/null +++ b/chapter_16/README.md @@ -0,0 +1,85 @@ + +An enormous thank-you to the National Oceanic & Atmospheric Administration and affiliated researchers + + + +Data was cleaned and converted to CSV using [OpenRefine](http://openrefine.org). + + + + +### mauna_loa_co2_monthly_averages.csv + +This file was derived from data provided by the National Oceanic & Atmospheric Administration’s Earth System Research Laboratory, Dr. Pieter Tans, NOAA/ESRL (www.esrl.noaa.gov/gmd/ccgg/trends/) and Dr. Ralph Keeling, Scripps Institution of Oceanography (scrippsco2.ucsd.edu/). + +“Mauna Loa CO2 monthly mean data” + +As accessed on February 27, 2017 from: +ftp://aftp.cmdl.noaa.gov/products/trends/co2/co2_mm_mlo.txt + +Source page and more info: +https://www.esrl.noaa.gov/gmd/ccgg/trends/data.html + + + + + + + + + +### METHANE + +This file was derived from data provided by + + + +“Atmospheric Methane Dry Air Mole Fractions from the NOAA ESRL GMD Carbon Cycle Cooperative Global Air Sampling Network, 1983-2015” + +As accessed on March 1, 2017 from: +ftp://aftp.cmdl.noaa.gov/data/trace_gases/ch4/flask/surface/ch4_mlo_surface-flask_1_ccgg_month.txt + + +See README: +ftp://aftp.cmdl.noaa.gov/data/trace_gases/ch4/flask/surface/README_surface_flask_ch4.html + +Full citation: + +Dlugokencky, E.J., P.M. Lang, A.M. Crotwell, J.W. Mund, M.J. Crotwell, and K.W. Thoning (2016), Atmospheric Methane Dry Air Mole Fractions from the NOAA ESRL Carbon Cycle Cooperative Global Air Sampling Network, 1983-2015, Version: 2016-07-07, Path: ftp://aftp.cmdl.noaa.gov/data/trace_gases/ch4/flask/surface/. + + + + + + + + +### N2O + +“Nitrous Oxide (N2O) data from hourly in situ samples analyzed on a gas chromatograph located at Mauna Loa (MLO), Hawaii (19.539 N, 155.578 W, elevation: 3397 m).” + +RITS (1987-2000) +ftp://ftp.cmdl.noaa.gov/data/hats/n2o/insituGCs/RITS/monthly/mlo_N2O_MM.dat + + +CATS (1999-2017) +ftp://aftp.cmdl.noaa.gov/data/hats/n2o/insituGCs/CATS/monthly/mlo_N2O_MM.dat + + + + + + + +### O3 + +As accessed on March 1, 2017 from: +ftp://aftp.cmdl.noaa.gov/data/ozwv/SurfaceOzone/MLO/ + + +README +ftp://aftp.cmdl.noaa.gov/data/ozwv/SurfaceOzone/readmeSO.pdf + +Full citation: + +McClure-Begley, A., Petropavlovskikh, I., Oltmans, S., (2014) NOAA Global Monitoring Surface Ozone Network. 1973-2014. National Oceanic and Atmospheric Administration, Earth Systems Research Laboratory Global Monitoring Division. Boulder, CO. March 1, 2017. http://dx.doi.org/10.7289/V57P8WBF From 80a200a59504bfb6f99312595ac67f41f8b5f7cf Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 1 Mar 2017 21:38:45 -0800 Subject: [PATCH 39/85] New ch 12 examples in progress --- chapter_12/01_enter_merge_exit.html | 211 ++++++++++++++++++++++++++++ chapter_12/02_paragraphs.html | 30 ++++ 2 files changed, 241 insertions(+) create mode 100644 chapter_12/01_enter_merge_exit.html create mode 100644 chapter_12/02_paragraphs.html diff --git a/chapter_12/01_enter_merge_exit.html b/chapter_12/01_enter_merge_exit.html new file mode 100644 index 0000000..f4cd385 --- /dev/null +++ b/chapter_12/01_enter_merge_exit.html @@ -0,0 +1,211 @@ + + + + + D3: Adding and removing values from a chart (dynamic labels included) + + + + + +

Add a new data value

+

Remove a data value

+ + + + \ No newline at end of file diff --git a/chapter_12/02_paragraphs.html b/chapter_12/02_paragraphs.html new file mode 100644 index 0000000..4ee0a12 --- /dev/null +++ b/chapter_12/02_paragraphs.html @@ -0,0 +1,30 @@ + + + + + D3: Setting paragraphs' style conditionally, based on data + + + + + + \ No newline at end of file From 6d114e7e3193e1f2ca7d693f57615528492aa895 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 2 Mar 2017 15:45:39 -0800 Subject: [PATCH 40/85] ch 12 in progress --- chapter_12/01_enter_merge_exit.html | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/chapter_12/01_enter_merge_exit.html b/chapter_12/01_enter_merge_exit.html index f4cd385..2b58e56 100644 --- a/chapter_12/01_enter_merge_exit.html +++ b/chapter_12/01_enter_merge_exit.html @@ -2,7 +2,7 @@ - D3: Adding and removing values from a chart (dynamic labels included) + D3: Logging out selections from the data join process + + + +

+ +

+ + + + \ No newline at end of file diff --git a/chapter_12/04_radios.html b/chapter_12/04_radios.html new file mode 100644 index 0000000..f759b00 --- /dev/null +++ b/chapter_12/04_radios.html @@ -0,0 +1,114 @@ + + + + + D3: Using radio buttons to set filter threshold value + + + + + +

+ 0 + 200 + 500 + 800 +

+ + + + \ No newline at end of file diff --git a/chapter_12/05_combinations.html b/chapter_12/05_combinations.html new file mode 100644 index 0000000..93ddad1 --- /dev/null +++ b/chapter_12/05_combinations.html @@ -0,0 +1,114 @@ + + + + + D3: Using radio buttons to trigger different combinations of filters + + + + + +

+ 0 + 200 + 500 + 800 +

+ + + + \ No newline at end of file From 6483d690ebed1d9b6e0d7b16cd422ac2c490c267 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 8 Mar 2017 20:33:39 -0800 Subject: [PATCH 43/85] Finished ch 12 examples --- chapter_12/05_combinations.html | 82 +++++++++++++++++++---- chapter_12/06_each.html | 115 ++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 12 deletions(-) create mode 100644 chapter_12/06_each.html diff --git a/chapter_12/05_combinations.html b/chapter_12/05_combinations.html index 93ddad1..d5395e2 100644 --- a/chapter_12/05_combinations.html +++ b/chapter_12/05_combinations.html @@ -20,17 +20,17 @@

- 0 - 200 - 500 - 800 + None + Center + Edges + Quadrants

+ + + + +

+ +

+ + + + \ No newline at end of file From cb4fc85b1fd2f31e9b8078eb63946c9d4e005176 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 9 Mar 2017 20:25:49 -0800 Subject: [PATCH 44/85] Tweak force draggable example --- chapter_13/07_force_draggable.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/chapter_13/07_force_draggable.html b/chapter_13/07_force_draggable.html index 9635ea7..c0807e5 100644 --- a/chapter_13/07_force_draggable.html +++ b/chapter_13/07_force_draggable.html @@ -78,9 +78,9 @@ return colors(i); }) .call(d3.drag() //Define what to do on drag events - .on("start", dragstarted) - .on("drag", dragged) - .on("end", dragended)); + .on("start", dragStarted) + .on("drag", dragging) + .on("end", dragEnded)); //Add a simple tooltip nodes.append("title") @@ -102,18 +102,18 @@ }); //Define drag event functions - function dragstarted(d) { + function dragStarted(d) { if (!d3.event.active) force.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } - function dragged(d) { + function dragging(d) { d.fx = d3.event.x; d.fy = d3.event.y; } - function dragended(d) { + function dragEnded(d) { if (!d3.event.active) force.alphaTarget(0); d.fx = null; d.fy = null; From ffcb0b64a8d12c234af622fca532d36352d779ab Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 9 Mar 2017 20:57:55 -0800 Subject: [PATCH 45/85] Ch 13 example added --- chapter_13/06_stacked_area.html | 153 ++++++++++++++++++ chapter_13/{06_force.html => 07_force.html} | 0 ...draggable.html => 08_force_draggable.html} | 0 3 files changed, 153 insertions(+) create mode 100644 chapter_13/06_stacked_area.html rename chapter_13/{06_force.html => 07_force.html} (100%) rename chapter_13/{07_force_draggable.html => 08_force_draggable.html} (100%) diff --git a/chapter_13/06_stacked_area.html b/chapter_13/06_stacked_area.html new file mode 100644 index 0000000..f3333d3 --- /dev/null +++ b/chapter_13/06_stacked_area.html @@ -0,0 +1,153 @@ + + + + + D3: Line chart, labeled + + + + + + + \ No newline at end of file diff --git a/chapter_13/06_force.html b/chapter_13/07_force.html similarity index 100% rename from chapter_13/06_force.html rename to chapter_13/07_force.html diff --git a/chapter_13/07_force_draggable.html b/chapter_13/08_force_draggable.html similarity index 100% rename from chapter_13/07_force_draggable.html rename to chapter_13/08_force_draggable.html From aee3ffa75514f859f7d7cafb074c72c2fd2007ea Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 16 Mar 2017 16:05:51 -0700 Subject: [PATCH 46/85] Added new stacked area chart example --- chapter_13/06_stacked_area.html | 159 +++++++++++++++++--------------- chapter_13/README.md | 15 +++ chapter_13/ev_sales_data.csv | 32 +++++++ 3 files changed, 132 insertions(+), 74 deletions(-) create mode 100644 chapter_13/README.md create mode 100644 chapter_13/ev_sales_data.csv diff --git a/chapter_13/06_stacked_area.html b/chapter_13/06_stacked_area.html index f3333d3..8c7c3a2 100644 --- a/chapter_13/06_stacked_area.html +++ b/chapter_13/06_stacked_area.html @@ -2,66 +2,85 @@ - D3: Line chart, labeled + D3: Stacked area chart +

Monthly Number of Electric Vehicles Sold in the U.S.: December 2010–June 2013

diff --git a/chapter_13/README.md b/chapter_13/README.md new file mode 100644 index 0000000..cec8eea --- /dev/null +++ b/chapter_13/README.md @@ -0,0 +1,15 @@ + +### ev_sales_data.csv + +This file was derived from data compiled by Yan (Joann) Zhou at Argonne National Laboratory, U.S. Department of Energy, and published by the DOE’s Office of Public Affairs, accompanied by a chart by Daniel Wood, Data Visualization and Cartographic Specialist in that office. + +Notes: Sales from the second quarter of 2013 for Tesla Model S are based off of estimates provided by the Hybrid Market Dashboard. Data last updated 1/20/15. + +“Electric and Hybrid Electric Vehicle Sales: December 2010 - June 2013” + +As accessed on March 14, 2017 from: +https://energy.gov/sites/prod/files/2013/07/f2/062010-092013_EV_HEV%20Sales.xlsx + +Source pages and more info: +https://energy.gov/downloads/electric-and-hybrid-electric-vehicle-sales-december-2010-june-2013 +https://energy.gov/articles/visualizing-electric-vehicle-sales diff --git a/chapter_13/ev_sales_data.csv b/chapter_13/ev_sales_data.csv new file mode 100644 index 0000000..3509c74 --- /dev/null +++ b/chapter_13/ev_sales_data.csv @@ -0,0 +1,32 @@ +Date,Nissan Leaf,Smart ED,Mitsubishi I EV,BMW Active E,Ford Focus,Honda Fit EV,Tesla Model S,Toyota RAV4 EV,Chevrolet Spark +2010-12,19,0,,,,,,, +2011-01,87,16,,,,,,, +2011-02,67,16,,,,,,, +2011-03,298,0,,,,,,, +2011-04,573,0,,,,,,, +2011-05,1142,8,,,,,,, +2011-06,1708,0,,,,,,, +2011-07,931,1,,,,,,, +2011-08,1362,1,,,,,,, +2011-09,1031,0,,,,,,, +2011-10,849,17,,,,,,, +2011-11,672,101,,,,,,, +2011-12,954,182,76,,,,,, +2012-01,676,0,36,112,,,,, +2012-02,478,2,44,115,,,,, +2012-03,579,0,56,326,,,,, +2012-04,370,0,79,30,,,,, +2012-05,510,0,85,11,6,,,, +2012-06,535,127,33,79,89,,,, +2012-07,395,6,33,0,38,7,,, +2012-08,685,1,37,0,34,9,100,, +2012-09,984,0,36,0,59,16,150,61, +2012-10,1579,0,30,-2,118,16,450,47, +2012-11,1539,3,42,0,172,26,800,32, +2012-12,1489,0,77,0,167,19,900,52, +2013-01,650,1,257,0,81,8,1350,25, +2013-02,653,1,337,0,158,15,1450,52, +2013-03,2236,0,31,0,180,23,1950,133, +2013-04,1937,0,127,0,147,22,2100,70, +2013-05,2138,60,91,0,157,15,2000,84, +2013-06,2225,53,39,0,177,208,1800,44,27 \ No newline at end of file From 4b9f4452d3939d3d7ff527de8cf9a85afa4ad103 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 17 Mar 2017 15:36:52 -0700 Subject: [PATCH 47/85] Source data updates --- chapter_14/05_choropleth.html | 2 +- chapter_14/06_points.html | 2 +- chapter_14/07_points_sized.html | 2 +- chapter_14/README.md | 15 ++- ...tivity-2004.csv => us-ag-productivity.csv} | 0 chapter_14/us-cities.csv | 100 +++++++++--------- 6 files changed, 63 insertions(+), 58 deletions(-) rename chapter_14/{us-ag-productivity-2004.csv => us-ag-productivity.csv} (100%) diff --git a/chapter_14/05_choropleth.html b/chapter_14/05_choropleth.html index eb39baa..0dfaaf7 100644 --- a/chapter_14/05_choropleth.html +++ b/chapter_14/05_choropleth.html @@ -37,7 +37,7 @@ .attr("height", h); //Load in agriculture data - d3.csv("us-ag-productivity-2004.csv", function(data) { + d3.csv("us-ag-productivity.csv", function(data) { //Set input domain for color scale color.domain([ diff --git a/chapter_14/06_points.html b/chapter_14/06_points.html index d26f908..26c575d 100644 --- a/chapter_14/06_points.html +++ b/chapter_14/06_points.html @@ -39,7 +39,7 @@ .attr("height", h); //Load in agriculture data - d3.csv("us-ag-productivity-2004.csv", function(data) { + d3.csv("us-ag-productivity.csv", function(data) { //Set input domain for color scale color.domain([ diff --git a/chapter_14/07_points_sized.html b/chapter_14/07_points_sized.html index a7b2b22..f8de370 100644 --- a/chapter_14/07_points_sized.html +++ b/chapter_14/07_points_sized.html @@ -39,7 +39,7 @@ .attr("height", h); //Load in agriculture data - d3.csv("us-ag-productivity-2004.csv", function(data) { + d3.csv("us-ag-productivity.csv", function(data) { //Set input domain for color scale color.domain([ diff --git a/chapter_14/README.md b/chapter_14/README.md index afe178a..bd4401a 100644 --- a/chapter_14/README.md +++ b/chapter_14/README.md @@ -1,7 +1,7 @@ ### us-states.json -This file consists of GeoJSON data generated by Mike Bostock from US Census data, and is in the public domain. This file used to be included in earlier versions of the D3 repository, and included this summary on its origins: +This file consists of GeoJSON data generated by Mike Bostock from U.S. Census data, and is in the public domain. This file used to be included in earlier versions of the D3 repository, and included this summary on its origins: > These are derived from the cartographic boundary files from the 2000 [U.S. Census](http://www.census.gov/geo/www/cob/bdy_files.html ). Then, MapShaper was used to simplify the geometry, and ogr2ogr to convert the shapefiles to GeoJSON. Some additional work was done to preserve the FIPS codes, which are dropped from the shapefiles by MapShaper. @@ -9,24 +9,29 @@ This file consists of GeoJSON data generated by Mike Bostock from US Census data -### us-ag-productivity-2004.csv +### us-ag-productivity.csv This file consists of data provided by the USDA, and is in the public domain. The values report agricultural productivity, by state, for 2004. Values are relative to an arbitrary baseline of the productivity of the state of Alabama in 1996 (1.0). "Table 19. Indices of total factor productivity by State, 1960-2004" + http://ers.usda.gov/data-products/agricultural-productivity-in-the-us.aspx ### us-cities.csv -File derived from data provided by the United States Census Bureau, and integrated with geocoding data from: http://www.gpsvisualizer.com/geocoder/ +File derived from data provided by the United States Census Bureau, and integrated with geocoding data from: http://www.gpsvisualizer.com/geocoder/ and http://www.teczno.com/squares/ -"Table 1. Annual Estimates of the Resident Population for Incorporated Places Over 50,000, Ranked by July 1, 2011 Population: April 1, 2010 to July 1, 2011" -http://www.census.gov/popest/data/cities/totals/2011/tables/SUB-EST2011-01.csv +Special thanks to Jeff Weiss for manually verifying and correcting coordinates within. "Annual Estimates of the Resident Population for Incorporated Places of 50,000 or More, Ranked by July 1, 2015 Population: April 1, 2010 to July 1, 2015" +Source: U.S. Census Bureau, Population Division +Release Date: May 2016 + https://www.census.gov/data/tables/2015/demo/popest/total-cities-and-towns.html + + diff --git a/chapter_14/us-ag-productivity-2004.csv b/chapter_14/us-ag-productivity.csv similarity index 100% rename from chapter_14/us-ag-productivity-2004.csv rename to chapter_14/us-ag-productivity.csv diff --git a/chapter_14/us-cities.csv b/chapter_14/us-cities.csv index 1cb36d1..8634498 100644 --- a/chapter_14/us-cities.csv +++ b/chapter_14/us-cities.csv @@ -1,51 +1,51 @@ rank,place,population,lat,lon -1,New York city,8175133,40.71455,-74.007124 -2,Los Angeles city,3792621,34.05349,-118.245319 -3,Chicago city,2695598,41.88415,-87.632409 -4,Houston city,2099451,29.76045,-95.369784 -5,Philadelphia city,1526006,39.95228,-75.162454 -6,Phoenix city,1445632,33.44826,-112.075774 -7,San Antonio city,1327407,29.42449,-98.494619 -8,San Diego city,1307402,32.715695,-117.161719 -9,Dallas city,1197816,32.778155,-96.795404 -10,San Jose city,945942,37.338475,-121.885794 -11,Jacksonville city,821784,30.33147,-81.656219 -12,Indianapolis city (balance),820445,39.76691,-86.149964 -13,Austin city,790390,30.267605,-97.742984 -14,San Francisco city,805235,37.777125,-122.419644 -15,Columbus city,787033,39.96196,-83.002984 -16,Fort Worth city,741206,32.748855,-97.329389 -17,Charlotte city,731424,35.22269,-80.837764 -18,Detroit city,713777,42.331685,-83.047924 -19,El Paso city,649121,31.759165,-106.487494 -20,Memphis city,646889,35.149766,-90.049259 -21,Boston city,617594,42.358635,-71.056699 -22,Seattle city,608660,47.60356,-122.329439 -23,Denver city,600158,39.74001,-104.992259 -24,Baltimore city,620961,39.290585,-76.609264 -25,Washington city,601723,38.89037,-77.031959 -26,Nashville-Davidson metropolitan government (balance),601222,36.167783,-86.778365 -27,Louisville/Jefferson County metro government (balance),597337,38.25486,-85.766404 -28,Milwaukee city,594833,43.04181,-87.906844 -29,Portland city,583776,45.511795,-122.675629 -30,Oklahoma City city,579999,35.472015,-97.520354 -31,Las Vegas city,583756,36.171915,-115.139974 -32,Albuquerque city,545852,35.08418,-106.648639 -33,Tucson city,520116,32.221553,-110.969754 -34,Fresno city,494665,36.740685,-119.785734 -35,Sacramento city,466488,38.579065,-121.491014 -36,Long Beach city,462257,33.766725,-118.192399 -37,Kansas City city,459787,39.11338,-94.626824 -38,Mesa city,439041,33.417045,-111.831459 -39,Virginia Beach city,437994,36.75502,-76.059204 -40,Atlanta city,420003,33.748315,-84.391109 -41,Colorado Springs city,416427,38.83345,-104.821814 -42,Raleigh city,403892,35.78551,-78.642669 -43,Omaha city,408958,41.260675,-95.940469 -44,Miami city,399457,25.728985,-80.237419 -45,Tulsa city,391906,36.149745,-95.993334 -46,Oakland city,390724,37.805065,-122.273024 -47,Cleveland city,396815,41.50438,-81.690434 -48,Minneapolis city,382578,44.979035,-93.264929 -49,Wichita city,382368,37.68698,-97.335579 -50,Arlington city,365438,38.89051,-77.086294 +1,New York,8550405,40.71455,-74.007124 +2,Los Angeles,3971883,34.05349,-118.245319 +3,Chicago,2720546,41.88415,-87.632409 +4,Houston,2296224,29.76045,-95.369784 +5,Philadelphia,1567442,39.95228,-75.162454 +6,Phoenix,1563025,33.44826,-112.075774 +7,San Antonio,1469845,29.42449,-98.494619 +8,San Diego,1394928,32.715695,-117.161719 +9,Dallas,1300092,32.778155,-96.795404 +10,San Jose,1026908,37.338475,-121.885794 +11,Austin,931830,30.267605,-97.742984 +12,Jacksonville,868031,30.33147,-81.656219 +13,San Francisco,864816,37.777125,-122.419644 +14,Indianapolis,853173,39.76691,-86.149964 +15,Columbus,850106,39.96196,-83.002984 +16,Fort Worth,833319,32.748855,-97.329389 +17,Charlotte,827097,35.22269,-80.837764 +18,Seattle,684451,47.60356,-122.329439 +19,Denver,682545,39.74001,-104.992259 +20,El Paso,681124,31.759165,-106.487494 +21,Detroit,677116,42.331685,-83.047924 +22,Washington,672228,38.89037,-77.031959 +23,Boston,667137,42.358635,-71.056699 +24,Memphis,655770,35.149766,-90.049259 +25,Nashville-Davidson,654610,36.167783,-86.778365 +26,Portland,632309,45.511795,-122.675629 +27,Oklahoma City,631346,35.472015,-97.520354 +28,Las Vegas,623747,36.171915,-115.139974 +29,Baltimore,621849,39.290585,-76.609264 +30,Louisville/Jefferson County,615366,38.25486,-85.766404 +31,Milwaukee,600155,43.04181,-87.906844 +32,Albuquerque,559121,35.08418,-106.648639 +33,Tucson,531641,32.221553,-110.969754 +34,Fresno,520052,36.740685,-119.785734 +35,Sacramento,490712,38.579065,-121.491014 +36,Kansas City,475378,39.11338,-94.626824 +37,Long Beach,474140,33.766725,-118.192399 +38,Mesa,471825,33.417045,-111.831459 +39,Atlanta,463878,33.748315,-84.391109 +40,Colorado Springs,456568,38.83345,-104.821814 +41,Virginia Beach,452745,36.75502,-76.059204 +42,Raleigh,451066,35.78551,-78.642669 +43,Omaha,443885,41.260675,-95.940469 +44,Miami,441003,25.728985,-80.237419 +45,Oakland,419267,37.805065,-122.273024 +46,Minneapolis,410939,44.979035,-93.264929 +47,Tulsa,403505,36.149745,-95.993334 +48,Wichita,389965,37.68698,-97.335579 +49,New Orleans,389617,29.9564,-90.0758 +50,Arlington,388125,38.89051,-77.086294 \ No newline at end of file From f669ea87b4d4cfcbdbf14d5070aead92f86b0606 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 20 Mar 2017 15:26:30 -0700 Subject: [PATCH 48/85] Added new panning example, moving others around --- chapter_14/08_pan.html | 267 ++++++++++++++++++ .../{08_oceans.html => z08_oceans.html} | 0 .../{09_mercator.html => z09_mercator.html} | 0 3 files changed, 267 insertions(+) create mode 100644 chapter_14/08_pan.html rename chapter_14/{08_oceans.html => z08_oceans.html} (100%) rename chapter_14/{09_mercator.html => z09_mercator.html} (100%) diff --git a/chapter_14/08_pan.html b/chapter_14/08_pan.html new file mode 100644 index 0000000..2e06525 --- /dev/null +++ b/chapter_14/08_pan.html @@ -0,0 +1,267 @@ + + + + + D3: Panning the map + + + + + + + \ No newline at end of file diff --git a/chapter_14/08_oceans.html b/chapter_14/z08_oceans.html similarity index 100% rename from chapter_14/08_oceans.html rename to chapter_14/z08_oceans.html diff --git a/chapter_14/09_mercator.html b/chapter_14/z09_mercator.html similarity index 100% rename from chapter_14/09_mercator.html rename to chapter_14/z09_mercator.html From 7dea6870799eea12532336fb830e6d563d629a06 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 20 Mar 2017 16:46:25 -0700 Subject: [PATCH 49/85] Adding pan examples --- chapter_14/09_pan_transition.html | 269 ++++++++++++++++++++++++++++++ chapter_14/10_pan_draggable.html | 269 ++++++++++++++++++++++++++++++ 2 files changed, 538 insertions(+) create mode 100644 chapter_14/09_pan_transition.html create mode 100644 chapter_14/10_pan_draggable.html diff --git a/chapter_14/09_pan_transition.html b/chapter_14/09_pan_transition.html new file mode 100644 index 0000000..105ba9a --- /dev/null +++ b/chapter_14/09_pan_transition.html @@ -0,0 +1,269 @@ + + + + + D3: Panning the map, with transitions + + + + + + + \ No newline at end of file diff --git a/chapter_14/10_pan_draggable.html b/chapter_14/10_pan_draggable.html new file mode 100644 index 0000000..105ba9a --- /dev/null +++ b/chapter_14/10_pan_draggable.html @@ -0,0 +1,269 @@ + + + + + D3: Panning the map, with transitions + + + + + + + \ No newline at end of file From 12978d4731f0152aaee75a4970a162ec0c8f1279 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 23 Mar 2017 11:13:05 -0700 Subject: [PATCH 50/85] Ch 14 mapping pan zoom examples in progress --- chapter_14/10_pan_draggable.html | 48 +++- chapter_14/11_pan_draggable_bgrect.html | 317 +++++++++++++++++++++++ chapter_14/12_zoom.html | 326 ++++++++++++++++++++++++ chapter_14/13_zoom_buttons_fixed.html | 326 ++++++++++++++++++++++++ chapter_14/z10_pan_draggable_zoomy.html | 312 +++++++++++++++++++++++ 5 files changed, 1325 insertions(+), 4 deletions(-) create mode 100644 chapter_14/11_pan_draggable_bgrect.html create mode 100644 chapter_14/12_zoom.html create mode 100644 chapter_14/13_zoom_buttons_fixed.html create mode 100644 chapter_14/z10_pan_draggable_zoomy.html diff --git a/chapter_14/10_pan_draggable.html b/chapter_14/10_pan_draggable.html index 105ba9a..65b9057 100644 --- a/chapter_14/10_pan_draggable.html +++ b/chapter_14/10_pan_draggable.html @@ -2,7 +2,7 @@ - D3: Panning the map, with transitions + D3: Dragging the map + + + + + \ No newline at end of file diff --git a/chapter_14/12_zoom.html b/chapter_14/12_zoom.html new file mode 100644 index 0000000..e495585 --- /dev/null +++ b/chapter_14/12_zoom.html @@ -0,0 +1,326 @@ + + + + + D3: Zooming the map + + + + + + + \ No newline at end of file diff --git a/chapter_14/13_zoom_buttons_fixed.html b/chapter_14/13_zoom_buttons_fixed.html new file mode 100644 index 0000000..e495585 --- /dev/null +++ b/chapter_14/13_zoom_buttons_fixed.html @@ -0,0 +1,326 @@ + + + + + D3: Zooming the map + + + + + + + \ No newline at end of file diff --git a/chapter_14/z10_pan_draggable_zoomy.html b/chapter_14/z10_pan_draggable_zoomy.html new file mode 100644 index 0000000..60bf349 --- /dev/null +++ b/chapter_14/z10_pan_draggable_zoomy.html @@ -0,0 +1,312 @@ + + + + + D3: Panning the map, with transitions + + + + + + + \ No newline at end of file From 9166fb38bbf15d0d02100871410885c51234e4ba Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 23 Mar 2017 15:38:08 -0700 Subject: [PATCH 51/85] Ch 14 map example edits --- chapter_14/08_pan.html | 8 +- chapter_14/09_pan_transition.html | 8 +- chapter_14/10_pan_draggable.html | 8 +- chapter_14/11_pan_draggable_bgrect.html | 8 +- chapter_14/12_zoom.html | 8 +- ...ed.html => 13_zoom_pan_buttons_fixed.html} | 49 ++-- ...e_zoomy.html => 14_zoom_with_buttons.html} | 228 +++++++++++++----- 7 files changed, 209 insertions(+), 108 deletions(-) rename chapter_14/{13_zoom_buttons_fixed.html => 13_zoom_pan_buttons_fixed.html} (89%) rename chapter_14/{z10_pan_draggable_zoomy.html => 14_zoom_with_buttons.html} (58%) diff --git a/chapter_14/08_pan.html b/chapter_14/08_pan.html index 2e06525..91fafe1 100644 --- a/chapter_14/08_pan.html +++ b/chapter_14/08_pan.html @@ -161,7 +161,7 @@ north.append("text") .attr("x", w/2) .attr("y", 20) - .html("↑") + .html("↑"); //South var south = svg.append("g") @@ -177,7 +177,7 @@ south.append("text") .attr("x", w/2) .attr("y", h - 10) - .html("↓") + .html("↓"); //West var west = svg.append("g") @@ -193,7 +193,7 @@ west.append("text") .attr("x", 15) .attr("y", h/2) - .html("←") + .html("←"); //East var east = svg.append("g") @@ -209,7 +209,7 @@ east.append("text") .attr("x", w - 15) .attr("y", h/2) - .html("→") + .html("→"); //Panning interaction diff --git a/chapter_14/09_pan_transition.html b/chapter_14/09_pan_transition.html index 105ba9a..8b6d6db 100644 --- a/chapter_14/09_pan_transition.html +++ b/chapter_14/09_pan_transition.html @@ -161,7 +161,7 @@ north.append("text") .attr("x", w/2) .attr("y", 20) - .html("↑") + .html("↑"); //South var south = svg.append("g") @@ -177,7 +177,7 @@ south.append("text") .attr("x", w/2) .attr("y", h - 10) - .html("↓") + .html("↓"); //West var west = svg.append("g") @@ -193,7 +193,7 @@ west.append("text") .attr("x", 15) .attr("y", h/2) - .html("←") + .html("←"); //East var east = svg.append("g") @@ -209,7 +209,7 @@ east.append("text") .attr("x", w - 15) .attr("y", h/2) - .html("→") + .html("→"); //Panning interaction diff --git a/chapter_14/10_pan_draggable.html b/chapter_14/10_pan_draggable.html index 65b9057..fbbf443 100644 --- a/chapter_14/10_pan_draggable.html +++ b/chapter_14/10_pan_draggable.html @@ -201,7 +201,7 @@ north.append("text") .attr("x", w/2) .attr("y", 20) - .html("↑") + .html("↑"); //South var south = svg.append("g") @@ -217,7 +217,7 @@ south.append("text") .attr("x", w/2) .attr("y", h - 10) - .html("↓") + .html("↓"); //West var west = svg.append("g") @@ -233,7 +233,7 @@ west.append("text") .attr("x", 15) .attr("y", h/2) - .html("←") + .html("←"); //East var east = svg.append("g") @@ -249,7 +249,7 @@ east.append("text") .attr("x", w - 15) .attr("y", h/2) - .html("→") + .html("→"); //Panning interaction diff --git a/chapter_14/11_pan_draggable_bgrect.html b/chapter_14/11_pan_draggable_bgrect.html index f17fa32..bb697f9 100644 --- a/chapter_14/11_pan_draggable_bgrect.html +++ b/chapter_14/11_pan_draggable_bgrect.html @@ -209,7 +209,7 @@ north.append("text") .attr("x", w/2) .attr("y", 20) - .html("↑") + .html("↑"); //South var south = svg.append("g") @@ -225,7 +225,7 @@ south.append("text") .attr("x", w/2) .attr("y", h - 10) - .html("↓") + .html("↓"); //West var west = svg.append("g") @@ -241,7 +241,7 @@ west.append("text") .attr("x", 15) .attr("y", h/2) - .html("←") + .html("←"); //East var east = svg.append("g") @@ -257,7 +257,7 @@ east.append("text") .attr("x", w - 15) .attr("y", h/2) - .html("→") + .html("→"); //Panning interaction diff --git a/chapter_14/12_zoom.html b/chapter_14/12_zoom.html index e495585..ea67d72 100644 --- a/chapter_14/12_zoom.html +++ b/chapter_14/12_zoom.html @@ -218,7 +218,7 @@ north.append("text") .attr("x", w/2) .attr("y", 20) - .html("↑") + .html("↑"); //South var south = svg.append("g") @@ -234,7 +234,7 @@ south.append("text") .attr("x", w/2) .attr("y", h - 10) - .html("↓") + .html("↓"); //West var west = svg.append("g") @@ -250,7 +250,7 @@ west.append("text") .attr("x", 15) .attr("y", h/2) - .html("←") + .html("←"); //East var east = svg.append("g") @@ -266,7 +266,7 @@ east.append("text") .attr("x", w - 15) .attr("y", h/2) - .html("→") + .html("→"); //Panning interaction diff --git a/chapter_14/13_zoom_buttons_fixed.html b/chapter_14/13_zoom_pan_buttons_fixed.html similarity index 89% rename from chapter_14/13_zoom_buttons_fixed.html rename to chapter_14/13_zoom_pan_buttons_fixed.html index e495585..9e812bd 100644 --- a/chapter_14/13_zoom_buttons_fixed.html +++ b/chapter_14/13_zoom_pan_buttons_fixed.html @@ -2,7 +2,7 @@ - D3: Zooming the map + D3: Zooming the map, with pan buttons fixed + + + + + \ No newline at end of file diff --git a/chapter_14/16_combo_zoom_pan.html b/chapter_14/16_combo_zoom_pan.html new file mode 100644 index 0000000..54e56cb --- /dev/null +++ b/chapter_14/16_combo_zoom_pan.html @@ -0,0 +1,438 @@ + + + + + D3: Zoom and pan presets + + + + +
+ + +
+ + + \ No newline at end of file diff --git a/chapter_14/17_labels.html b/chapter_14/17_labels.html new file mode 100644 index 0000000..c2e04c9 --- /dev/null +++ b/chapter_14/17_labels.html @@ -0,0 +1,474 @@ + + + + + D3: Map value labels + + + + +
+ + +
+ + + \ No newline at end of file From 2fc080aa555c1d1f4bc56042334871a91ae62a8c Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sun, 26 Mar 2017 23:04:36 -0700 Subject: [PATCH 56/85] Mapping nav adjustments --- chapter_14/12_zoom.html | 3 --- chapter_14/13_zoom_pan_buttons_fixed.html | 22 ++++++-------------- chapter_14/14_zoom_with_buttons.html | 25 ++++++----------------- chapter_14/15_extents.html | 25 ++++++----------------- chapter_14/16_combo_zoom_pan.html | 25 ++++++----------------- chapter_14/17_labels.html | 25 ++++++----------------- 6 files changed, 30 insertions(+), 95 deletions(-) diff --git a/chapter_14/12_zoom.html b/chapter_14/12_zoom.html index ea67d72..8a2581a 100644 --- a/chapter_14/12_zoom.html +++ b/chapter_14/12_zoom.html @@ -59,9 +59,6 @@ //Log out d3.event.transform, so you can see all the goodies inside //console.log(d3.event.transform); - //Log out what the transform saved to the map is at this moment - //console.log(d3.zoomTransform(map.node())); - //New offset array var offset = [d3.event.transform.x, d3.event.transform.y]; diff --git a/chapter_14/13_zoom_pan_buttons_fixed.html b/chapter_14/13_zoom_pan_buttons_fixed.html index 9e812bd..f1d8e0b 100644 --- a/chapter_14/13_zoom_pan_buttons_fixed.html +++ b/chapter_14/13_zoom_pan_buttons_fixed.html @@ -59,9 +59,6 @@ //Log out d3.event.transform, so you can see all the goodies inside //console.log(d3.event.transform); - //Log out what the transform saved to the map is at this moment - //console.log(d3.zoomTransform(map.node())); - //New offset array var offset = [d3.event.transform.x, d3.event.transform.y]; @@ -273,16 +270,13 @@ d3.selectAll(".pan") .on("click", function() { - //Get current translation offset - var transform = d3.zoomTransform(map.node()); - - var x = transform.x; - var y = transform.y; - var k = transform.k; - //Set how much to move on each click var moveAmount = 50; + //Set x/y to zero for now + var x = 0; + var y = 0; + //Which way are we headed? var direction = d3.select(this).attr("id"); @@ -304,13 +298,9 @@ break; } - //Transition to new zoom transform values - // - //This triggers a zoom event, specifying a new 'zoomIdentity' - //with our new x and y values (and unchanged k value). - // + //This triggers a zoom event, translating by x, y map.transition() - .call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(k)); + .call(zoom.translateBy, x, y); }); diff --git a/chapter_14/14_zoom_with_buttons.html b/chapter_14/14_zoom_with_buttons.html index 2867031..5ccea6b 100644 --- a/chapter_14/14_zoom_with_buttons.html +++ b/chapter_14/14_zoom_with_buttons.html @@ -68,9 +68,6 @@ //Log out d3.event.transform, so you can see all the goodies inside //console.log(d3.event.transform); - //Log out what the transform saved to the map is at this moment - //console.log(d3.zoomTransform(map.node())); - //New offset array var offset = [d3.event.transform.x, d3.event.transform.y]; @@ -283,16 +280,13 @@ d3.selectAll(".pan") .on("click", function() { - //Get current translation offset - var transform = d3.zoomTransform(map.node()); - - var x = transform.x; - var y = transform.y; - var k = transform.k; - //Set how much to move on each click var moveAmount = 50; + //Set x/y to zero for now + var x = 0; + var y = 0; + //Which way are we headed? var direction = d3.select(this).attr("id"); @@ -314,13 +308,9 @@ break; } - //Transition to new zoom transform values - // - //This triggers a zoom event, specifying a new 'zoomIdentity' - //with our new x and y values (and unchanged k value). - // + //This triggers a zoom event, translating by x, y map.transition() - .call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(k)); + .call(zoom.translateBy, x, y); }); @@ -388,10 +378,7 @@ break; } - //Transition to new zoom transform values - // //This triggers a zoom event, scaling by 'scaleFactor' - // map.transition() .call(zoom.scaleBy, scaleFactor); diff --git a/chapter_14/15_extents.html b/chapter_14/15_extents.html index 9666e67..547d597 100644 --- a/chapter_14/15_extents.html +++ b/chapter_14/15_extents.html @@ -68,9 +68,6 @@ //Log out d3.event.transform, so you can see all the goodies inside //console.log(d3.event.transform); - //Log out what the transform saved to the map is at this moment - //console.log(d3.zoomTransform(map.node())); - //New offset array var offset = [d3.event.transform.x, d3.event.transform.y]; @@ -285,16 +282,13 @@ d3.selectAll(".pan") .on("click", function() { - //Get current translation offset - var transform = d3.zoomTransform(map.node()); - - var x = transform.x; - var y = transform.y; - var k = transform.k; - //Set how much to move on each click var moveAmount = 50; + //Set x/y to zero for now + var x = 0; + var y = 0; + //Which way are we headed? var direction = d3.select(this).attr("id"); @@ -316,13 +310,9 @@ break; } - //Transition to new zoom transform values - // - //This triggers a zoom event, specifying a new 'zoomIdentity' - //with our new x and y values (and unchanged k value). - // + //This triggers a zoom event, translating by x, y map.transition() - .call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(k)); + .call(zoom.translateBy, x, y); }); @@ -390,10 +380,7 @@ break; } - //Transition to new zoom transform values - // //This triggers a zoom event, scaling by 'scaleFactor' - // map.transition() .call(zoom.scaleBy, scaleFactor); diff --git a/chapter_14/16_combo_zoom_pan.html b/chapter_14/16_combo_zoom_pan.html index 54e56cb..d11f1bb 100644 --- a/chapter_14/16_combo_zoom_pan.html +++ b/chapter_14/16_combo_zoom_pan.html @@ -76,9 +76,6 @@ //Log out d3.event.transform, so you can see all the goodies inside //console.log(d3.event.transform); - //Log out what the transform saved to the map is at this moment - //console.log(d3.zoomTransform(map.node())); - //New offset array var offset = [d3.event.transform.x, d3.event.transform.y]; @@ -293,16 +290,13 @@ d3.selectAll(".pan") .on("click", function() { - //Get current translation offset - var transform = d3.zoomTransform(map.node()); - - var x = transform.x; - var y = transform.y; - var k = transform.k; - //Set how much to move on each click var moveAmount = 50; + //Set x/y to zero for now + var x = 0; + var y = 0; + //Which way are we headed? var direction = d3.select(this).attr("id"); @@ -324,13 +318,9 @@ break; } - //Transition to new zoom transform values - // - //This triggers a zoom event, specifying a new 'zoomIdentity' - //with our new x and y values (and unchanged k value). - // + //This triggers a zoom event, translating by x, y map.transition() - .call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(k)); + .call(zoom.translateBy, x, y); }); @@ -398,10 +388,7 @@ break; } - //Transition to new zoom transform values - // //This triggers a zoom event, scaling by 'scaleFactor' - // map.transition() .call(zoom.scaleBy, scaleFactor); diff --git a/chapter_14/17_labels.html b/chapter_14/17_labels.html index c2e04c9..9b8ef29 100644 --- a/chapter_14/17_labels.html +++ b/chapter_14/17_labels.html @@ -86,9 +86,6 @@ //Log out d3.event.transform, so you can see all the goodies inside //console.log(d3.event.transform); - //Log out what the transform saved to the map is at this moment - //console.log(d3.zoomTransform(map.node())); - //New offset array var offset = [d3.event.transform.x, d3.event.transform.y]; @@ -329,16 +326,13 @@ d3.selectAll(".pan") .on("click", function() { - //Get current translation offset - var transform = d3.zoomTransform(map.node()); - - var x = transform.x; - var y = transform.y; - var k = transform.k; - //Set how much to move on each click var moveAmount = 50; + //Set x/y to zero for now + var x = 0; + var y = 0; + //Which way are we headed? var direction = d3.select(this).attr("id"); @@ -360,13 +354,9 @@ break; } - //Transition to new zoom transform values - // - //This triggers a zoom event, specifying a new 'zoomIdentity' - //with our new x and y values (and unchanged k value). - // + //This triggers a zoom event, translating by x, y map.transition() - .call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(k)); + .call(zoom.translateBy, x, y); }); @@ -434,10 +424,7 @@ break; } - //Transition to new zoom transform values - // //This triggers a zoom event, scaling by 'scaleFactor' - // map.transition() .call(zoom.scaleBy, scaleFactor); From 2c5dc59cf7b3852277a24397f85d405c48cbe001 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 28 Mar 2017 16:28:12 -0700 Subject: [PATCH 57/85] Rename to finish ch 14 examples --- chapter_14/{z08_oceans.html => 18_oceans.html} | 0 chapter_14/{z09_mercator.html => 19_mercator.html} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename chapter_14/{z08_oceans.html => 18_oceans.html} (100%) rename chapter_14/{z09_mercator.html => 19_mercator.html} (100%) diff --git a/chapter_14/z08_oceans.html b/chapter_14/18_oceans.html similarity index 100% rename from chapter_14/z08_oceans.html rename to chapter_14/18_oceans.html diff --git a/chapter_14/z09_mercator.html b/chapter_14/19_mercator.html similarity index 100% rename from chapter_14/z09_mercator.html rename to chapter_14/19_mercator.html From 90e8f10c09d9864cb4d49134e89e8e6c83a71c39 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 7 Apr 2017 20:58:32 -0700 Subject: [PATCH 58/85] Ch 16 examples setup --- chapter_16/01_stacked_area.html | 164 ++++++++++++++++++++++++++++++ chapter_16/README.md | 28 +++++ chapter_16/vehicle_sales_data.csv | 149 +++++++++++++++++++++++++++ 3 files changed, 341 insertions(+) create mode 100644 chapter_16/01_stacked_area.html create mode 100644 chapter_16/vehicle_sales_data.csv diff --git a/chapter_16/01_stacked_area.html b/chapter_16/01_stacked_area.html new file mode 100644 index 0000000..477a4f6 --- /dev/null +++ b/chapter_16/01_stacked_area.html @@ -0,0 +1,164 @@ + + + + + D3: All vehicles + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005–Feburary 2017

+ + + \ No newline at end of file diff --git a/chapter_16/README.md b/chapter_16/README.md index 715eae8..1962c99 100644 --- a/chapter_16/README.md +++ b/chapter_16/README.md @@ -1,4 +1,32 @@ + +XXXX VEHICLES + +### ev_sales_data.csv + +XXXXX OLD + +This file was derived from data compiled by Yan (Joann) Zhou at Argonne National Laboratory, U.S. Department of Energy, and published by the DOE’s Office of Public Affairs, accompanied by a chart by Daniel Wood, Data Visualization and Cartographic Specialist in that office. + +Notes: Sales from the second quarter of 2013 for Tesla Model S are based off of estimates provided by the Hybrid Market Dashboard. Data last updated 1/20/15. + +“Electric and Hybrid Electric Vehicle Sales: December 2010 - June 2013” + +As accessed on March 14, 2017 from: +https://energy.gov/sites/prod/files/2013/07/f2/062010-092013_EV_HEV%20Sales.xlsx + +Source pages and more info: +https://energy.gov/downloads/electric-and-hybrid-electric-vehicle-sales-december-2010-june-2013 +https://energy.gov/articles/visualizing-electric-vehicle-sales + + + + + + + +XXXXX CLIMATE + An enormous thank-you to the National Oceanic & Atmospheric Administration and affiliated researchers diff --git a/chapter_16/vehicle_sales_data.csv b/chapter_16/vehicle_sales_data.csv new file mode 100644 index 0000000..1bdc5d1 --- /dev/null +++ b/chapter_16/vehicle_sales_data.csv @@ -0,0 +1,149 @@ +Make,Honda,Toyota,Honda,Ford,Honda,Toyota,Lexus,Toyota,Lexus,Lexus,Nissan,Lexus,Saturn,Chevrolet,Chevrolet,Saturn,Dodge,Chevrolet,Ford,Mercedes-Benz,Mercedes-Benz,Mercedes-Benz,Mazda,BMW,BMW,Honda,Lincoln,Porsche,Lexus,Volkswagen,Infinity,Hyundai,Buick,Buick,Porsche,Kia,Acura,Ford,Lexus,Audi,Toyota,Volkswagen,Mercedes-Benz,Infiniti,Chevrolet,Infiniti,Nissan,Subaru,Acura,Lexus,Toyota,Acura,Kia,Hyundai,Chevrolet,Prius,Ford,Honda,Ford,Porsche,Cadillac,BMW,Porsche,Mercedes-Benz,Volvo,BMW,Hyundai,Audi,BMW,Mercedes-Benz,BMW,Mercedes-Benz,Kia,Nissan,Smart,Mitsubishi,BMW,Ford,Honda,Tesla,Toyota,Chevrolet,Fiat,BMW,Mercedes-Benz,Volkswagen,Kia,Tesla,Chevrolet,Hyundai,Toyota,Honda +Model,Insight,Prius,Civic,Escape,Accord,Highlander,RX 450h,Camry,GS 450h,HS 250h,Altima,LS 600hL,Vue,Tahoe,Malibu,Aura,Durango,Silverado,Fusion,S400,ML450,E320,Tribute,X6,Activehybrid3&5&7,CR-z,MKZ,Cayenne,CT 200h,Touareg,Q70 (M35h),Sonata,LaCrosse,Regal,Panamera S,Optima,ILX,C-Max,ES Hybrid,Q5 Hybrid,Avalon,Jetta,E400H,Q50,Impala Hybrid,QX60,Pathfinder Hybrid,XV,RLX,NX Hybrid,RAV4,NSX,Niro Hybrid,Ioniq Hybrid,Volt,PHEV,C-Max Energi,Accord,Fusion Energi,Panamera S E-Hybrid,ELR,i8,Cayenne S E-hybrid,S550 Plug,XC90 Plug In,X5,Sonata Plug In,A3 Plug In,3-series Plug-In,GLE 550e,7-series Plug-in,C350We,Optima Plug-in,LEAF,ED,I EV,Active E,Focus,Fit EV,Model S,RAV4 EV,Spark,500E,i3,B-Class,e-Golf,Soul EV,Model X,Bolt,Tucson,Mirai,Clarity +Type,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,FCEV,FCEV,FCEV +2005-01,7,5566,1169,908,805,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-02,22,7078,1353,1092,855,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-03,56,10236,2896,1569,1862,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-04,90,11345,3466,1705,2023,,2345,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-05,52,9461,1895,1234,1314,35,2931,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-06,69,9622,1852,1126,1080,2869,2605,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-07,68,9691,2329,1168,1376,2564,2262,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-08,80,9850,4146,1363,2336,2925,2607,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-09,83,8193,1916,1808,2352,2715,2113,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-10,37,9939,231,1313,1266,2330,1904,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-11,60,7889,2083,1121,837,2353,1722,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2005-12,42,9027,2528,1553,720,2198,2172,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-01,59,7654,3166,898,351,2263,1477,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-02,72,6547,1781,1341,783,2631,1803,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-03,79,7922,2232,1590,581,2987,2470,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-04,110,8234,3087,3420,614,3768,2247,86,141,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-05,92,8103,2890,2862,520,3755,2006,3032,294,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-06,77,9696,2601,1884,396,2705,1190,4268,231,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-07,91,11114,2673,2060,504,2784,1220,5023,157,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-08,109,11177,3411,1789,499,2581,1514,4977,192,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-09,19,10492,2508,1651,389,2347,1687,4044,164,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-10,9,8733,2288,1602,287,1643,1239,2806,177,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-11,2,8008,2208,1484,311,1667,1327,3100,176,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2006-12,3,9291,2408,1968,363,2354,1981,4005,252,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-01,0,8299,1783,1238,248,1810,1245,2801,167,,,,793,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-02,0,12227,1924,1696,312,1892,1249,3332,160,,206,,793,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-03,1,19156,2813,2523,385,2501,1471,5144,181,,462,,793,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-04,2,13056,2855,2275,318,2394,1384,4410,174,,483,,793,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-05,0,24009,4520,3214,439,3312,1746,6853,181,,821,,797,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-06,0,17756,3246,2526,342,2403,1562,5530,131,,804,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-07,0,16062,2493,1578,260,1205,1385,4329,142,,1131,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-08,0,14055,2102,1833,275,378,1172,4284,130,,643,267,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-09,0,12494,2092,1652,229,193,979,4196,72,,756,196,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-10,0,13158,2286,2084,243,596,1392,3511,71,,927,175,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-11,0,16737,3238,2224,204,2577,1674,5118,100,,1191,170,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2007-12,0,14212,3223,2265,150,2791,2032,4969,136,,964,129,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-01,0,11379,1745,1474,48,2143,1211,3750,64,,473,105,135,233,112,14,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-02,0,10895,1808,1743,42,1938,1148,4121,77,,529,112,135,234,112,14,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-03,0,20635,3769,2008,53,2239,1570,6930,65,,832,113,135,234,112,14,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-04,0,21757,4324,1907,25,2578,1624,6678,82,,801,122,135,234,112,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-05,0,15011,4676,2378,16,2644,2155,5999,98,,1607,112,340,589,282,36,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-06,0,11765,2710,1912,7,1511,1330,3054,73,,1333,73,277,547,295,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-07,0,14785,3440,1265,3,1371,1439,2645,40,,715,83,362,351,349,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-08,0,13463,3105,1338,2,1227,1277,3456,35,,442,71,417,798,388,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-09,0,10873,2020,990,0,921,744,2785,29,,470,47,443,1101,382,31,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-10,0,11804,1621,1997,1,1022,615,2792,22,,554,55,354,795,325,22,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-11,0,8660,1043,1361,0,907,624,2174,42,,353,37,328,767,195,45,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2008-12,0,7859,1036,1149,1,890,1463,1888,51,,710,50,338,1729,454,34,46,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-01,0,8121,1076,880,1,984,1556,1141,41,,644,33,153,599,145,19,42,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-02,0,7232,1362,1294,0,956,1502,2080,22,,463,22,188,632,197,23,0,47,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-03,569,8924,2869,1351,0,1037,1165,2554,42,,834,25,362,609,547,26,0,68,451,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-04,2096,8385,3361,1134,0,933,655,2198,33,,222,19,338,523,547,31,0,95,1165,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-05,2780,10091,2077,1827,0,1351,393,2941,43,,345,27,227,641,706,35,0,130,2079,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-06,2079,12998,1583,1405,0,1098,527,2093,27,,666,31,239,547,489,56,0,123,2244,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-07,2295,19173,969,2543,0,1171,1369,2509,45,,1030,28,269,538,476,24,0,180,2810,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-08,4226,18886,717,2102,0,836,1754,2114,48,543,3164,10,414,562,441,65,0,226,2593,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-09,1746,10984,152,878,0,269,1168,872,38,1242,345,12,90,615,156,30,0,120,1260,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-10,1739,13496,239,949,0,700,1567,1407,39,1527,299,21,56,792,114,30,0,167,1333,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-11,1403,9617,243,960,0,722,1210,1465,37,1407,503,15,134,489,212,29,0,156,1401,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2009-12,1639,11775,471,1157,0,1029,1598,1513,54,1980,842,15,186,645,132,159,0,279,1686,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-01,1307,8484,253,715,0,526,1016,867,41,1247,1059,9,14,278,67,25,0,97,1152,77,70,,43,22,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-02,2014,7968,346,782,0,339,890,1011,22,712,619,15,4,315,68,2,0,106,1317,77,69,,42,21,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-03,1652,11786,579,1282,0,594,1251,1549,31,1494,394,9,8,368,80,4,0,180,1784,98,67,,59,21,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-04,1880,12555,621,1119,0,692,1232,1655,25,1076,330,7,4,399,67,0,0,161,1607,108,37,,58,21,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-05,1913,14248,717,1383,0,683,1358,1455,38,1360,1167,8,3,565,41,2,0,337,2562,101,181,,61,12,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-06,1491,10998,595,1360,0,611,1304,1097,22,603,479,4,14,368,36,5,0,120,2103,63,212,,55,128,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-07,1858,14102,617,1220,0,575,1356,1276,16,165,378,14,0,262,14,4,0,135,1676,69,24,,68,3,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-08,2030,11799,761,790,0,486,1370,1165,15,594,284,15,2,252,12,3,0,379,3104,84,79,,55,3,26,694,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-09,1679,11394,667,842,0,523,1112,1104,18,711,511,9,0,215,2,1,0,232,1756,83,24,,53,2,9,1236,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-10,1965,11731,662,809,0,756,1402,1194,29,792,443,9,0,245,6,4,0,391,1816,114,2,,67,0,7,1419,366,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-11,1536,10224,612,814,0,722,1293,983,18,788,434,13,0,213,7,0,0,97,1586,39,0,,46,9,8,1024,392,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +2010-12,1637,15639,906,972,0,949,1535,1231,30,1121,612,17,1,377,5,5,0,158,1769,42,1,,48,6,25,876,424,206,,,,,,,,,,,,,,,,,,,,,,,,,,,326,,,,,,,,,,,,,,,,,,,19,0,,,,,,,,,,,,,,,,, +2011-01,1554,10635,653,520,0,689,912,860,19,286,365,8,0,217,0,0,0,213,969,26,1,,36,5,32,894,370,211,,65,,,,,,,,,,,,,,,,,,,,,,,,,321,,,,,,,,,,,,,,,,,,,87,16,,,,,,,,,,,,,,,,, +2011-02,1722,13539,532,795,0,707,999,993,33,183,366,7,0,191,0,0,0,67,1379,24,0,,37,9,35,1091,395,142,,60,,,,,,,,,,,,,,,,,,,,,,,,,281,,,,,,,,,,,,,,,,,,,67,16,,,,,,,,,,,,,,,,, +2011-03,2782,18605,441,1195,0,797,1438,1437,24,230,545,9,0,278,0,0,0,120,1466,25,0,,34,5,38,1685,615,114,2199,44,,,,,,,,,,,,,,,,,,,,,,,,,608,,,,,,,,,,,,,,,,,,,298,0,,,,,,,,,,,,,,,,, +2011-04,2644,12477,121,1070,0,380,1167,1110,29,279,334,10,0,276,0,0,0,119,1285,32,0,,37,2,32,1819,503,107,875,52,42,,,,,,,,,,,,,,,,,,,,,,,,493,,,,,,,,,,,,,,,,,,,573,0,,,,,,,,,,,,,,,,, +2011-05,1435,6924,268,1118,0,149,610,592,18,220,499,1,0,229,2,0,0,111,1256,49,0,,35,3,38,1557,561,114,454,40,36,,,,,,,,,,,,,,,,,,,,,,,,481,,,,,,,,,,,,,,,,,,,1142,8,,,,,,,,,,,,,,,,, +2011-06,1021,4340,418,826,0,74,413,449,24,159,250,4,0,129,22,0,0,90,969,26,0,59,64,6,27,966,483,177,240,23,33,1422,,,,,,,,,,,,,,,,,,,,,,,561,,,,,,,,,,,,,,,,,,,1708,0,,,,,,,,,,,,,,,,, +2011-07,987,7907,311,652,0,185,671,393,26,306,204,6,0,115,0,0,0,37,456,25,0,0,48,5,20,878,480,130,1553,14,35,4177,,,,,,,,,,,,,,,,,,,,,,,125,,,,,,,,,,,,,,,,,,,931,1,,,,,,,,,,,,,,,,, +2011-08,961,9491,106,563,0,226,841,318,17,284,318,9,0,76,0,0,0,23,216,15,0,0,51,0,15,745,491,128,2087,10,54,4136,,,,,,,,,,,,,,,,,,,,,,,302,,,,,,,,,,,,,,,,,,,1362,1,,,,,,,,,,,,,,,,, +2011-09,512,9325,305,566,0,218,650,229,18,231,217,8,0,31,0,0,0,82,552,22,0,0,32,4,16,537,455,112,1444,14,45,2000,,,,,,,,,,,,,,,,,,,,,,,723,,,,,,,,,,,,,,,,,,,1031,0,,,,,,,,,,,,,,,,, +2011-10,492,11008,480,573,0,239,861,333,19,205,49,9,0,88,0,0,0,53,857,9,0,0,38,2,9,289,477,107,1511,18,33,2001,297,,,,,,,,,,,,,,,,,,,,,,1108,,,,,,,,,,,,,,,,,,,849,17,,,,,,,,,,,,,,,,, +2011-11,749,15208,503,1131,0,322,928,730,22,207,55,5,0,79,0,0,0,45,993,19,0,0,36,-1,25,305,475,140,1759,21,46,1723,522,37,26,,,,,,,,,,,,,,,,,,,,1139,,,,,,,,,,,,,,,,,,,672,101,,,,,,,,,,,,,,,,, +2011-12,690,17004,565,1080,0,563,1233,1797,33,274,34,9,0,168,0,0,0,205,888,37,0,0,36,3,51,564,434,89,2259,29,54,1907,982,86,26,,,,,,,,,,,,,,,,,,,,1529,,,,,,,,,,,,,,,,,,,954,182,76,,,,,,,,,,,,,,,, +2012-01,492,11555,449,345,0,362,753,2116,25,152,27,8,0,76,1,0,0,25,611,11,0,0,24,0,31,363,253,112,1025,36,35,1304,781,63,39,705,,,,,,,,,,,,,,,,,,,603,,,,,,,,,,,,,,,,,,,676,0,36,112,,,,,,,,,,,,,,, +2012-02,773,20589,741,434,0,474,826,3750,20,150,22,6,0,151,350,0,0,54,1110,28,13,0,21,0,60,466,419,137,1640,18,58,1568,1248,137,34,925,,,,,,,,,,,,,,,,,,,1023,,,,,,,,,,,,,,,,,,,478,2,44,115,,,,,,,,,,,,,,, +2012-03,1032,27800,906,162,0,607,992,5404,12,261,18,5,0,227,1416,0,0,94,1009,10,0,0,29,2,54,536,626,124,2223,19,47,2095,1117,135,43,1201,,,,,,,,,,,,,,,,,,,2289,911,,,,,,,,,,,,,,,,,,579,0,56,326,,,,,,,,,,,,,,, +2012-04,738,23514,766,0,0,552,801,4406,10,28,10,8,0,144,1557,0,0,42,778,8,0,0,16,-1,29,334,397,104,1620,12,23,1847,1165,130,26,837,,,,,,,,,,,,,,,,,,,1462,1654,,,,,,,,,,,,,,,,,,370,0,79,30,,,,,,,,,,,,,,, +2012-05,512,20391,708,206,0,560,1011,4403,42,21,9,6,0,161,1642,0,0,62,683,7,0,0,0,1,26,296,480,150,1549,18,78,1869,1202,174,73,810,34,,,,,,,,,,,,,,,,,,1680,1086,,,,,,,,,,,,,,,,,,510,0,85,11,6,,,,,,,,,,,,,, +2012-06,494,18455,548,17,0,496,1193,3471,75,10,3,6,0,124,2002,0,0,38,797,8,3,0,0,1,9,409,451,42,1387,25,73,1884,1245,219,25,933,115,,,,,,,,,,,,,,,,,,1760,695,,,,,,,,,,,,,,,,,,535,127,33,79,89,,,,,,,,,,,,,, +2012-07,419,15955,471,50,0,469,1171,3197,60,5,7,1,0,132,1938,0,0,48,1109,5,2,0,0,1,21,330,594,60,1499,27,59,1888,867,233,35,848,110,0,,,,,,,,,,,,,,,,,1849,688,,,,,,,,,,,,,,,,,,395,6,33,0,38,7,,,,,,,,,,,,, +2012-08,341,20064,579,34,0,449,1170,3840,94,7,0,0,0,135,2414,0,0,96,1071,11,2,0,0,0,25,392,998,69,1472,17,60,1766,1024,331,48,907,136,0,817,,,,,,,,,,,,,,,,2831,1047,,,,,,,,,,,,,,,,,,685,1,37,0,34,9,100,,,,,,,,,,,, +2012-09,246,17280,493,81,0,413,944,3704,89,8,3,1,0,110,1656,0,0,29,898,9,2,0,0,0,40,335,781,84,1195,5,45,1560,840,463,86,902,140,969,1400,25,,,,,,,,,,,,,,,2851,1652,,,,,,,,,,,,,,,,,,984,0,36,0,59,16,150,61,,,,,,,,,,, +2012-10,251,14885,453,9,0,466,997,2986,68,3,3,5,0,146,1266,0,0,72,956,10,0,0,0,-1,321,244,465,106,1199,11,66,1510,978,287,48,745,144,3038,1520,33,,,,,,,,,,,,,,,2961,1889,144,,,,,,,,,,,,,,,,,1579,0,30,-2,118,16,450,47,,,,,,,,,,, +2012-11,238,14739,530,21,0,485,971,3936,60,3,1,2,0,171,1041,0,0,188,1834,4,0,0,0,2,214,244,282,108,1264,44,71,1589,724,211,67,681,174,3589,1424,90,,,,,,,,,,,,,,,1519,1766,1259,,,,,,,,,,,,,,,,,1539,3,42,0,172,26,800,32,,,,,,,,,,, +2012-12,310,18679,512,82,0,588,1394,4443,52,2,0,6,0,224,1381,0,0,192,3244,10,0,0,0,-1,206,243,321,84,1598,18,76,1874,819,181,46,751,119,3339,1866,122,747,162,,,,,,,,,,,,,2633,1361,971,,,,,,,,,,,,,,,,,1489,0,77,0,167,19,900,52,,,,,,,,,,, +2013-01,319,14898,429,0,0,452,744,3826,34,0,0,14,0,97,981,0,0,19,3043,12,3,0,0,0,77,358,100,60,1001,21,37,1192,576,184,46,909,84,2387,1324,90,1040,232,22,,,,,,,,,,,,1140,874,338,2,0,,,,,,,,,,,,,,,650,1,257,0,81,8,1350,25,,,,,,,,,,, +2013-02,388,17119,433,0,17,441,756,4147,38,1,0,22,0,91,1254,0,0,21,3806,9,6,0,0,0,133,381,177,32,1182,43,46,1441,706,375,5,1215,154,2849,1154,76,1361,272,22,,,,,,,,,,,,1626,693,334,17,119,,,,,,,,,,,,,,,653,1,337,0,158,15,1450,52,,,,,,,,,,, +2013-03,454,21354,572,0,0,477,925,4461,56,1,0,12,0,109,1359,0,0,18,3417,8,0,0,0,0,133,451,446,46,1062,12,58,1623,717,387,11,1001,145,3275,1561,84,1616,451,25,,,,,,,,,,,,1478,786,494,26,295,,,,,,,,,,,,,,,2236,0,31,0,180,23,1950,133,,,,,,,,,,, +2013-04,391,19290,569,0,0,495,688,3257,34,0,0,15,0,116,1551,0,0,27,3625,7,0,0,0,0,223,405,884,46,1171,7,35,1447,662,389,5,1000,152,3197,1237,86,1423,353,17,,,,,,,,,,,,1306,599,411,55,364,,,,,,,,,,,,,,,1937,0,127,0,147,22,2100,70,,,,,,,,,,, +2013-05,426,22844,570,0,0,545,885,4265,39,0,0,11,0,154,1695,0,0,20,3335,8,0,0,0,0,138,427,715,48,1623,6,42,1817,668,291,7,1206,195,3261,1434,105,1514,473,29,,,,,,,,,,,,1607,678,450,58,416,,,,,,,,,,,,,,,2138,60,91,0,157,15,2000,84,,,,,,,,,,, +2013-06,384,20495,568,0,0,550,900,3878,55,1,0,10,0,120,1651,0,0,13,3057,5,0,0,0,0,134,393,768,62,1513,12,47,2129,619,227,4,1100,163,2889,1239,83,1394,438,23,,,,,,,,,,,,2698,584,455,42,390,,,,,,,,,,,,,,,2225,53,39,0,177,208,1800,44,27,,,,,,,,,, +2013-07,420,22477,578,0,0,410,962,4193,63,2,0,6,0,58,1338,0,0,10,2914,8,2,0,0,0,129,384,646,39,1306,3,33,2200,530,183,29,1241,110,2267,1324,47,1139,417,26,,,,,,,,,,,,1788,817,433,54,407,,,,,,,,,,,,,,,1864,58,46,0,150,63,1550,109,103,,,,,,,,,, +2013-08,438,25567,697,0,0,440,1116,4729,69,0,0,5,0,83,1582,0,0,13,3694,2,0,0,0,0,95,483,791,43,1784,7,44,2303,803,214,0,1601,125,2411,1600,73,1467,712,29,0,,,,,,,,,,,3351,1791,621,44,600,,,,,,,,,,,,,,,2420,182,30,0,175,66,1700,231,102,50,,,,,,,,, +2013-09,299,14738,402,0,0,325,815,3069,31,0,0,3,0,45,858,0,0,6,2265,0,0,0,0,0,59,264,619,67,798,3,33,2102,423,185,2,1272,108,1424,1223,73,1104,887,27,47,,,,,,,,,,,1766,1152,758,51,750,,,,,,,,,,,,,,,1953,137,20,0,110,35,1100,167,78,50,,,,,,,,, +2013-10,463,13528,1158,0,23,331,1258,2903,34,0,0,6,0,55,819,0,0,9,2577,0,0,0,0,0,85,325,717,59,842,1,34,1318,552,178,4,1151,137,1438,1367,56,1398,666,22,51,5,,,,,,,,,,2022,2095,1092,71,1087,,,,,,,,,,,,,,,2002,111,28,0,115,40,1300,0,87,50,,,,,,,,, +2013-11,402,15029,1031,0,530,332,1105,2994,25,0,0,5,0,51,425,0,0,7,2769,3,0,0,0,0,106,295,852,58,1002,1,33,1866,430,187,0,1233,44,1457,1393,38,1532,394,20,118,16,302,0,,,,,,,,1920,1100,941,68,870,4,0,,,,,,,,,,,,,2003,153,12,0,130,23,1400,62,87,60,,,,,,,,, +2013-12,418,14801,712,0,426,272,1153,2726,44,0,0,6,0,57,266,0,0,6,2768,2,0,0,0,0,144,384,754,55,1787,2,33,2121,447,93,0,990,44,1201,1706,43,1480,360,20,91,35,374,334,,,,,,,,2392,919,827,38,791,47,6,,,,,,,,,,,,,2529,167,11,0,158,51,1700,28,76,50,,,,,,,,, +2014-01,317,11402,439,0,525,145,637,1978,30,0,0,11,0,21,232,0,0,1,2607,1,1,0,0,0,34,267,726,45,1290,3,44,1340,445,78,0,777,27,947,866,36,970,224,23,59,34,238,265,470,,,,,,,918,803,471,27,533,141,41,,,,,,,,,,,,,1252,97,1,0,100,30,1300,63,93,35,,,,,,,,, +2014-02,339,11820,443,0,910,105,621,2517,23,0,0,11,0,12,202,0,0,3,3096,2,2,0,0,0,39,318,919,64,1230,0,14,1907,506,88,0,960,42,1301,945,24,613,232,15,328,38,135,191,546,,,,,,,1210,1041,552,24,779,57,58,,,,,,,,,,,,,1425,122,3,0,129,33,1400,101,71,40,,,,,,,,, +2014-03,410,17130,338,0,1346,333,852,4287,25,0,0,7,0,26,191,0,0,1,3903,1,0,0,0,0,43,354,1411,96,1480,4,19,2430,536,95,0,1879,46,1685,1384,35,1600,276,9,380,49,167,237,725,,,,,,,1478,1452,610,18,899,56,81,,,,,,,,,,,,,2507,186,24,0,177,37,1300,73,108,166,,,,,,,,, +2014-04,441,16270,450,0,1442,418,387,3916,35,0,0,9,0,14,130,0,0,3,3537,0,0,0,0,0,25,369,1047,84,1054,3,11,2055,716,41,0,1060,49,1586,1242,21,1522,149,39,263,34,114,183,711,,,,,,,1548,1741,525,37,743,63,61,,,,,,,,,,,,,2088,203,12,0,116,50,1400,69,97,152,,,,,,,,, +2014-05,493,24101,415,0,1530,355,837,5199,9,0,0,5,0,14,94,0,0,4,4641,0,7,0,0,0,30,389,1128,75,1762,3,12,2094,772,64,0,735,63,2051,1408,25,1957,209,16,294,58,137,238,1003,,,,,,,1684,2692,782,46,1342,53,52,,,,,,,,,,,,,3117,206,35,0,177,33,1400,149,182,167,336,,,,,,,, +2014-06,333,17078,410,0,1135,280,872,3874,15,0,0,5,0,21,62,0,0,9,3016,0,0,0,0,0,37,302,787,72,1521,6,11,1523,610,75,0,1006,44,1952,1102,19,1437,206,13,242,63,108,191,788,,,,,,,1777,1571,988,28,1939,111,97,,,,,,,,,,,,,2347,278,22,0,197,38,1400,91,85,166,358,,,,,,6,, +2014-07,291,19304,409,0,1362,214,914,4609,8,0,0,6,0,6,30,0,0,1,2851,0,0,0,0,0,16,356,638,159,1979,2,8,2800,462,34,0,1155,35,2163,1358,22,1767,156,5,246,43,112,221,746,,,,,,,2020,1371,831,41,1226,63,188,,,,,,,,,,,,,3019,298,17,0,198,42,1400,68,128,119,363,41,,,,,10,, +2014-08,290,22619,503,0,1175,288,1090,4320,13,0,0,4,0,7,21,0,0,1,2943,0,0,0,0,0,16,342,758,14,2191,4,5,1910,545,47,0,1318,24,2451,1628,31,2049,151,7,266,63,130,237,747,,,,,,,2511,818,1050,46,1222,68,196,9,,,,,,,,,,,,3186,208,20,0,264,55,1200,228,80,166,1025,51,,,,,10,, +2014-09,240,13924,360,0,1095,303,695,1986,3,0,0,0,0,2,10,0,0,1,1972,1,0,0,0,0,32,248,645,13,1078,1,6,2134,587,32,0,1003,15,1109,1128,19,1437,114,12,274,35,109,160,571,31,,,,,,1394,353,677,42,640,82,111,58,,,,,,,,,,,,2881,182,15,0,176,29,1300,125,51,137,1022,65,0,,,,6,, +2014-10,222,13032,395,0,1130,327,728,2161,2,0,0,2,0,5,17,0,0,1,2164,0,0,0,0,0,9,205,662,18,1158,1,13,1181,704,40,0,1483,15,1318,1182,24,1330,97,5,296,32,114,166,617,36,,,,,,1439,479,644,34,686,97,152,204,,,,,,,,,,,,2589,150,17,0,186,23,1300,97,58,140,1159,98,1,109,,,1,, +2014-11,278,13506,432,0,1094,425,788,2220,9,0,0,1,0,6,14,0,0,4,2323,1,0,0,0,0,10,188,569,10,1322,1,17,781,772,46,0,1101,10,1296,1194,16,1212,68,5,422,23,146,187,575,37,,,,,,1336,451,644,43,752,57,155,126,45,,,,,,,,,,,2687,313,18,0,191,5,1450,83,61,100,816,193,119,140,,,10,, +2014-12,311,13922,476,0,1233,428,930,2448,11,0,0,4,0,3,15,0,0,1,2372,4,10,0,0,0,17,224,743,0,1608,2,20,897,698,22,0,1299,9,1303,1400,11,1154,57,9,386,93,168,204,427,29,354,,,,,1490,492,659,63,789,31,118,158,67,,,,,,,,,,,3102,351,12,0,53,32,1900,37,131,115,1013,326,237,110,,,12,, +2015-01,223,11843,320,0,805,268,521,2143,8,0,0,5,0,3,6,0,0,2,1782,0,0,0,0,0,7,196,468,0,1005,2,19,672,326,12,0,844,3,765,746,8,912,50,30,297,19,129,184,512,14,163,,,,,542,401,395,28,426,61,92,85,83,,,,,,,,,,,1070,147,3,0,85,0,1300,7,86,119,670,240,181,69,,,6,, +2015-02,211,11621,358,0,832,256,494,2110,10,0,0,7,0,8,8,0,0,0,2416,0,0,0,0,0,1,175,480,0,978,1,14,1605,514,20,0,856,5,878,758,10,864,36,3,365,19,179,212,549,21,164,,,,,693,397,498,12,603,40,127,113,106,,,,,,,,,,,1198,76,2,0,145,0,1400,2,119,117,1089,109,130,48,,,3,, +2015-03,209,15565,351,0,948,295,641,2739,9,0,0,7,0,1,8,0,0,0,2534,0,2,0,0,0,11,255,717,0,1416,3,22,1793,497,21,0,805,4,1054,1076,9,902,45,13,390,29,195,258,587,18,225,,,,,639,473,715,5,837,44,92,143,72,,,,,,,,,,,1817,103,10,0,140,1,2000,4,151,164,922,145,195,63,,,3,, +2015-04,183,14807,386,0,1118,305,492,2650,12,0,0,5,0,4,4,0,0,0,1820,1,2,0,0,0,3,216,810,0,1170,0,15,2481,531,28,0,892,2,1237,789,7,906,41,0,299,49,170,167,552,15,210,,,,,905,428,553,5,711,30,104,138,88,,,,,,,,,,,1553,124,16,0,124,0,1900,4,920,450,406,158,309,73,,,1,, +2015-05,139,18836,458,0,1463,323,551,3174,8,0,0,7,0,0,2,0,0,0,2440,0,0,0,0,0,7,246,1005,0,1436,6,14,2943,498,23,0,1046,4,1892,911,17,1114,55,2,342,53,188,223,557,24,250,,,,,1618,727,715,5,986,21,116,117,111,,,,,,,,,,,2104,102,18,0,165,0,2300,0,283,471,818,278,410,108,,,2,, +2015-06,126,14587,391,0,1241,311,486,2755,7,0,0,1,0,9,27,0,0,1,1691,0,5,0,0,0,8,204,700,0,1118,2,12,2334,341,17,0,897,1,1814,711,5,973,66,0,347,24,180,215,493,27,203,,,,,1225,464,667,4,727,34,62,137,89,,,,,,,,,,,2074,94,23,0,152,0,2800,0,226,411,551,242,293,109,,,2,, +2015-07,113,17340,463,0,1481,304,530,2756,11,0,0,5,0,0,1,0,0,0,2157,0,1,0,0,0,6,270,725,0,1374,1,11,1837,322,8,0,873,0,1225,891,8,1175,91,2,381,23,226,234,559,28,234,,,,,1313,584,693,1,852,23,66,217,77,10,,,,,,,,,,1174,109,12,0,135,0,1800,0,57,353,935,196,313,59,,,0,2, +2015-08,85,17413,590,0,1369,377,599,3314,4,0,0,3,0,0,0,0,0,0,2441,0,0,0,0,0,3,333,713,0,1504,0,13,1647,275,16,0,1167,0,1501,1281,5,1322,98,2,384,27,240,212,455,34,206,,,,,1380,344,723,2,949,36,45,210,83,10,4,,,,,,,,,1393,106,6,0,176,0,1600,0,135,370,792,172,381,93,,,1,0, +2015-09,64,15894,613,0,854,367,443,2629,7,0,0,3,0,0,1,0,0,0,2002,0,0,0,0,0,2,310,596,0,1131,0,12,1185,200,13,0,1136,2,1247,907,3,1064,77,0,356,5,231,186,370,26,170,,,,,949,216,719,0,808,41,36,182,70,17,0,,,,,,,,,1247,94,3,0,145,0,2400,0,157,347,1710,147,343,105,6,,5,2, +2015-10,53,15112,455,0,442,375,514,2545,7,0,0,1,0,0,1,0,0,0,2050,0,0,0,0,0,0,316,646,0,1077,0,14,1342,199,11,0,1262,0,912,895,5,993,64,1,381,11,220,168,211,14,188,,,,,2035,91,695,0,849,28,82,149,126,25,1,,,,,,,,,1238,75,9,0,126,1,2100,1,177,231,986,81,596,109,10,,1,38, +2015-11,30,12531,239,0,289,318,958,1964,5,0,0,0,0,0,0,0,0,0,1388,0,0,0,0,0,4,236,676,0,984,1,14,931,194,9,0,844,0,815,833,7,798,52,0,189,1,149,102,319,13,196,64,,,,1980,44,639,1,944,33,67,118,121,21,7,285,15,,,,,,,1054,178,4,0,93,0,3100,0,166,174,723,41,472,83,15,,0,23, +2015-12,22,15054,263,0,223,516,1493,1861,3,0,0,3,0,0,1,0,0,0,1960,0,0,0,0,0,11,316,867,0,1464,0,16,1138,145,8,0,870,1,837,1443,13,933,65,0,281,12,249,84,425,16,364,1430,,,,2114,22,579,1,1058,16,135,656,137,35,74,607,0,,,,,,,1347,179,9,0,96,0,3500,0,152,270,1422,97,609,96,177,,0,15, +2016-01,19,9301,161,0,71,375,790,1256,5,0,0,3,0,0,0,0,0,0,1373,0,0,0,0,0,2,192,491,0,622,0,10,964,118,3,0,469,0,637,622,3,583,46,1,175,12,119,65,261,0,245,1973,,,,996,10,350,0,581,27,67,32,146,19,226,181,175,327,,,,,,755,48,2,0,66,0,1300,0,139,217,182,58,328,81,400,,2,26, +2016-02,0,10544,143,0,68,396,752,1599,5,0,0,2,0,0,0,0,0,0,1764,0,0,0,0,0,0,128,585,0,762,0,10,1588,87,7,0,386,0,880,633,0,590,39,0,202,4,137,72,278,12,236,2462,,,,1126,6,490,0,932,33,91,54,172,36,176,345,200,248,,,,,,930,54,5,0,81,0,1900,0,216,195,248,37,198,60,500,,3,30, +2016-03,2,12068,166,0,51,492,886,1746,8,0,0,4,0,0,2,0,0,0,2057,0,0,0,0,0,1,163,608,0,972,0,12,1884,83,7,0,436,0,1092,894,5,776,47,1,335,4,195,87,329,19,251,3073,,,,1865,7,610,0,1238,23,104,89,244,12,178,313,275,332,29,,,,,1246,70,1,0,110,0,3000,0,252,373,332,66,86,79,1500,,4,41, +2016-04,9,11921,92,0,29,442,899,1975,16,0,0,5,0,0,1,0,0,0,2035,0,0,0,0,0,2,253,613,0,577,0,11,1788,115,14,0,483,1,1621,700,2,715,46,0,147,3,66,56,303,19,222,3807,,,,1983,4,607,0,1331,25,95,130,237,29,150,655,250,321,25,,,,,787,66,6,0,81,0,1700,0,419,372,814,56,326,139,1500,,4,41, +2016-05,9,12513,83,0,15,473,719,2055,7,0,0,2,0,0,246,0,0,0,1716,0,0,0,0,0,8,234,805,0,797,0,10,2513,42,7,0,570,0,1327,735,2,660,47,1,95,2,85,60,303,18,229,4185,,,,1901,4,538,0,1453,26,45,146,191,27,110,500,250,361,67,,,,,979,75,2,0,54,0,1500,0,394,388,696,49,269,120,2000,,4,40, +2016-06,9,11016,62,0,31,528,684,1649,3,0,0,1,0,0,371,0,0,0,2542,0,0,0,0,0,0,235,766,0,785,0,10,1242,60,4,0,483,0,1486,646,2,619,44,4,94,10,88,57,214,0,183,3751,2,,,1937,11,630,0,1700,22,94,169,176,27,166,583,200,353,26,19,,,,1096,53,4,0,54,0,2800,0,359,278,608,44,248,134,2000,,8,40, +2016-07,5,12690,60,0,565,524,684,2214,12,0,0,2,0,0,416,0,0,0,3519,0,0,0,0,0,3,272,681,0,849,1,10,1301,55,2,0,768,0,1112,705,1,707,87,2,112,0,74,55,193,11,228,4692,21,,,2406,4,755,0,1341,21,15,166,148,32,178,649,350,349,81,30,,,,1063,62,20,0,58,0,2400,0,333,274,1479,50,344,179,1500,,8,52, +2016-08,9,12982,50,0,890,506,574,2155,3,0,0,11,0,0,522,0,0,0,3002,0,0,0,0,0,0,222,541,0,819,0,9,1146,60,0,0,654,0,879,692,2,775,128,1,150,0,65,58,117,19,224,4919,22,,,2081,2,707,0,1422,59,6,145,197,30,176,876,250,346,51,24,,,,1066,55,25,0,75,0,3200,0,292,311,1013,57,454,153,1900,,2,371, +2016-09,1,12471,38,0,1160,383,387,1902,4,0,0,6,0,0,618,0,0,0,3776,0,0,0,0,0,7,165,460,0,638,0,8,1815,35,0,0,591,0,739,497,1,688,76,2,174,0,63,80,79,24,233,4127,38,,,2031,4,689,0,1652,28,6,158,131,41,148,482,275,312,54,26,,,,1316,44,17,0,82,0,4100,0,315,370,391,51,529,217,2600,,4,69, +2016-10,0,8132,14,0,1296,356,535,1802,0,0,0,0,0,0,600,0,0,0,4915,0,0,0,0,0,23,168,450,0,564,0,9,1479,53,0,0,482,0,398,353,0,673,48,0,148,0,59,64,44,13,188,3551,67,,,2191,0,571,0,1372,38,3,199,138,174,142,406,250,348,92,19,,,,1412,43,4,0,73,0,1200,0,260,319,442,58,407,190,1000,,0,103, +2016-11,3,9714,15,0,1879,483,666,1693,1,0,0,2,0,0,769,0,0,0,3372,0,0,0,0,0,18,146,552,0,550,0,7,1867,31,0,0,423,0,811,434,0,639,45,2,134,0,64,68,27,33,241,3757,51,,,2531,781,721,0,1817,88,5,173,179,52,161,436,275,394,215,30,,,,1457,47,5,0,66,0,1800,0,39,287,629,52,305,179,1400,,0,105, +2016-12,9,10803,12,0,3124,1018,985,2181,6,0,0,2,0,0,790,0,0,0,3577,0,0,0,0,0,0,160,667,0,968,0,12,1374,26,1,0,397,,895,734,0,1026,56,0,232,0,99,94,25,31,362,4773,68,,,3691,1641,1289,0,1099,3,3,133,152,71,204,569,250,589,240,83,23,171,,1899,40,3,0,101,0,5300,0,17,353,791,54,443,197,3300,579,1,116, +2017-01,1,6463,16,0,1711,571,443,1238,6,0,0,0,0,0,339,0,0,0,4856,0,0,0,0,0,0,89,467,0,393,0,5,1113,18,3,0,279,0,473,242,0,448,13,1,128,0,44,73,13,11,179,2898,50,42,4,1611,1366,473,0,606,2,3,50,177,55,96,262,150,387,129,52,18,210,40,772,15,0,0,56,0,1200,0,4,305,382,53,332,117,1000,1162,2,83,42 +2017-02,0,7682,8,0,1867,1339,507,1333,5,0,0,0,0,0,534,0,0,1,4939,0,0,0,0,0,0,118,570,0,458,0,4,1471,12,0,0,257,,676,330,0,464,12,0,138,0,53,90,6,27,184,3080,46,2143,1,1820,1362,639,0,837,1,0,58,121,51,83,275,250,400,144,59,35,51,61,1037,22,1,0,228,0,1700,0,4,283,318,56,293,152,800,952,5,110,27 \ No newline at end of file From d5563b91259f23fe801e7db8872a664870e0feb4 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sat, 15 Apr 2017 09:31:11 -0700 Subject: [PATCH 59/85] Ch 16 examples in progress --- chapter_16/01_stacked_area.html | 1 + chapter_16/z22_bar_page.html | 440 +++++++++++++++++++++ chapter_16/z23_bar_page_side_by_side.html | 442 ++++++++++++++++++++++ chapter_16/z5_framing.html | 200 ++++++++++ 4 files changed, 1083 insertions(+) create mode 100644 chapter_16/z22_bar_page.html create mode 100644 chapter_16/z23_bar_page_side_by_side.html create mode 100755 chapter_16/z5_framing.html diff --git a/chapter_16/01_stacked_area.html b/chapter_16/01_stacked_area.html index 477a4f6..0637c82 100644 --- a/chapter_16/01_stacked_area.html +++ b/chapter_16/01_stacked_area.html @@ -72,6 +72,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005&nda var dataset = data; console.log(dataset); + //xxxxx //Now that we know the column names in the data… var keys = dataset.columns; diff --git a/chapter_16/z22_bar_page.html b/chapter_16/z22_bar_page.html new file mode 100644 index 0000000..e0c0480 --- /dev/null +++ b/chapter_16/z22_bar_page.html @@ -0,0 +1,440 @@ + + + + + D3: Placing charts in a larger page layout + + + + + + + + +
+ +

Five New Data Insights You Have to See to Believe

+ +

You won’t believe your eyes when you realize what these charts are telling you. The numbers don’t lie, and sometimes facing the facts can cause a shock. No one could have predicted this, and no one knew it was true until we published these innovative visualizations, thereby proving definitively that a picture is worth a thousand words. (Edit the source to add more cliches here.)

+ +
+

Total sales by employee in July 2015

+
+ +
+

Total bonuses by employee in July 2015

+
+ +
+ +
+ + + +
+ + + + + + \ No newline at end of file diff --git a/chapter_16/z23_bar_page_side_by_side.html b/chapter_16/z23_bar_page_side_by_side.html new file mode 100644 index 0000000..9037fb1 --- /dev/null +++ b/chapter_16/z23_bar_page_side_by_side.html @@ -0,0 +1,442 @@ + + + + + D3: Dynamically sized charts happily coexist side-by-side + + + + + + + + +
+ +

Five New Data Insights You Have to See to Believe

+ +

You won’t believe your eyes when you realize what these charts are telling you. The numbers don’t lie, and sometimes facing the facts can cause a shock. No one could have predicted this, and no one knew it was true until we published these innovative visualizations, thereby proving definitively that a picture is worth a thousand words. (Edit the source to add more cliches here.)

+ +
+

Total sales by employee in July 2015

+
+ +
+

Total bonuses by employee in July 2015

+
+ +
+ +
+ + + +
+ + + + + + \ No newline at end of file diff --git a/chapter_16/z5_framing.html b/chapter_16/z5_framing.html new file mode 100755 index 0000000..b09840e --- /dev/null +++ b/chapter_16/z5_framing.html @@ -0,0 +1,200 @@ + + + + + Bar Chart, Framed + + + + + +
+ +

Not All Countries are Equally Satisfied

+ +

The OECD’s Better Life Index assigns each country a “Life Satisfaction” score. Source: OECD, 2014

+ +
+ + + + + \ No newline at end of file From 4bd46c60676d6d19a3a39b57da8f224043a38614 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sat, 15 Apr 2017 09:37:03 -0700 Subject: [PATCH 60/85] Minor spacing tidying --- chapter_14/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/chapter_14/README.md b/chapter_14/README.md index bd4401a..72f3ced 100644 --- a/chapter_14/README.md +++ b/chapter_14/README.md @@ -8,7 +8,6 @@ This file consists of GeoJSON data generated by Mike Bostock from U.S. Census da - ### us-ag-productivity.csv This file consists of data provided by the USDA, and is in the public domain. The values report agricultural productivity, by state, for 2004. Values are relative to an arbitrary baseline of the productivity of the state of Alabama in 1996 (1.0). @@ -33,5 +32,3 @@ Release Date: May 2016 https://www.census.gov/data/tables/2015/demo/popest/total-cities-and-towns.html - - From 6217fef6cace008ed88a6cd476c4766cce48a7da Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 17 Apr 2017 11:00:35 -0700 Subject: [PATCH 61/85] Ch 16 initial example --- chapter_16/01_initial_chart.html | 212 ++++++++++++++++++ chapter_16/01_stacked_area.html | 165 -------------- chapter_16/README.md | 114 +--------- chapter_16/zvehicle_sales_data_TRANSPOSED.csv | 93 ++++++++ 4 files changed, 311 insertions(+), 273 deletions(-) create mode 100644 chapter_16/01_initial_chart.html delete mode 100644 chapter_16/01_stacked_area.html create mode 100644 chapter_16/zvehicle_sales_data_TRANSPOSED.csv diff --git a/chapter_16/01_initial_chart.html b/chapter_16/01_initial_chart.html new file mode 100644 index 0000000..f4f0eac --- /dev/null +++ b/chapter_16/01_initial_chart.html @@ -0,0 +1,212 @@ + + + + + D3: All vehicles + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005–Feburary 2017

+ + + \ No newline at end of file diff --git a/chapter_16/01_stacked_area.html b/chapter_16/01_stacked_area.html deleted file mode 100644 index 0637c82..0000000 --- a/chapter_16/01_stacked_area.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - D3: All vehicles - - - - -

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005–Feburary 2017

- - - \ No newline at end of file diff --git a/chapter_16/README.md b/chapter_16/README.md index 1962c99..37b45cc 100644 --- a/chapter_16/README.md +++ b/chapter_16/README.md @@ -1,113 +1,11 @@ +### vehicle_sales_data.csv -XXXX VEHICLES +This file was derived from data compiled by Yan (Joann) Zhou at Argonne National Laboratory, U.S. Department of Energy, as provided by email on March 20, 2017. -### ev_sales_data.csv +Note: Some values are estimates, while a handful have been interpolated by me, to fit the structure needed for this example project. That is to say, I do not recommend using this derivative data for any other purposes; it is best to retrieve the original and make your own judgements about how to interpret it. -XXXXX OLD +“Light Duty Electric Drive Vehicles Monthly Sales Updates” -This file was derived from data compiled by Yan (Joann) Zhou at Argonne National Laboratory, U.S. Department of Energy, and published by the DOE’s Office of Public Affairs, accompanied by a chart by Daniel Wood, Data Visualization and Cartographic Specialist in that office. - -Notes: Sales from the second quarter of 2013 for Tesla Model S are based off of estimates provided by the Hybrid Market Dashboard. Data last updated 1/20/15. - -“Electric and Hybrid Electric Vehicle Sales: December 2010 - June 2013” - -As accessed on March 14, 2017 from: -https://energy.gov/sites/prod/files/2013/07/f2/062010-092013_EV_HEV%20Sales.xlsx - -Source pages and more info: -https://energy.gov/downloads/electric-and-hybrid-electric-vehicle-sales-december-2010-june-2013 -https://energy.gov/articles/visualizing-electric-vehicle-sales - - - - - - - -XXXXX CLIMATE - -An enormous thank-you to the National Oceanic & Atmospheric Administration and affiliated researchers - - - -Data was cleaned and converted to CSV using [OpenRefine](http://openrefine.org). - - - - -### mauna_loa_co2_monthly_averages.csv - -This file was derived from data provided by the National Oceanic & Atmospheric Administration’s Earth System Research Laboratory, Dr. Pieter Tans, NOAA/ESRL (www.esrl.noaa.gov/gmd/ccgg/trends/) and Dr. Ralph Keeling, Scripps Institution of Oceanography (scrippsco2.ucsd.edu/). - -“Mauna Loa CO2 monthly mean data” - -As accessed on February 27, 2017 from: -ftp://aftp.cmdl.noaa.gov/products/trends/co2/co2_mm_mlo.txt - -Source page and more info: -https://www.esrl.noaa.gov/gmd/ccgg/trends/data.html - - - - - - - - - -### METHANE - -This file was derived from data provided by - - - -“Atmospheric Methane Dry Air Mole Fractions from the NOAA ESRL GMD Carbon Cycle Cooperative Global Air Sampling Network, 1983-2015” - -As accessed on March 1, 2017 from: -ftp://aftp.cmdl.noaa.gov/data/trace_gases/ch4/flask/surface/ch4_mlo_surface-flask_1_ccgg_month.txt - - -See README: -ftp://aftp.cmdl.noaa.gov/data/trace_gases/ch4/flask/surface/README_surface_flask_ch4.html - -Full citation: - -Dlugokencky, E.J., P.M. Lang, A.M. Crotwell, J.W. Mund, M.J. Crotwell, and K.W. Thoning (2016), Atmospheric Methane Dry Air Mole Fractions from the NOAA ESRL Carbon Cycle Cooperative Global Air Sampling Network, 1983-2015, Version: 2016-07-07, Path: ftp://aftp.cmdl.noaa.gov/data/trace_gases/ch4/flask/surface/. - - - - - - - - -### N2O - -“Nitrous Oxide (N2O) data from hourly in situ samples analyzed on a gas chromatograph located at Mauna Loa (MLO), Hawaii (19.539 N, 155.578 W, elevation: 3397 m).” - -RITS (1987-2000) -ftp://ftp.cmdl.noaa.gov/data/hats/n2o/insituGCs/RITS/monthly/mlo_N2O_MM.dat - - -CATS (1999-2017) -ftp://aftp.cmdl.noaa.gov/data/hats/n2o/insituGCs/CATS/monthly/mlo_N2O_MM.dat - - - - - - - -### O3 - -As accessed on March 1, 2017 from: -ftp://aftp.cmdl.noaa.gov/data/ozwv/SurfaceOzone/MLO/ - - -README -ftp://aftp.cmdl.noaa.gov/data/ozwv/SurfaceOzone/readmeSO.pdf - -Full citation: - -McClure-Begley, A., Petropavlovskikh, I., Oltmans, S., (2014) NOAA Global Monitoring Surface Ozone Network. 1973-2014. National Oceanic and Atmospheric Administration, Earth Systems Research Laboratory Global Monitoring Division. Boulder, CO. March 1, 2017. http://dx.doi.org/10.7289/V57P8WBF +More info: +https://www.anl.gov/energy-systems/project/light-duty-electric-drive-vehicles-monthly-sales-updates diff --git a/chapter_16/zvehicle_sales_data_TRANSPOSED.csv b/chapter_16/zvehicle_sales_data_TRANSPOSED.csv new file mode 100644 index 0000000..7e81977 --- /dev/null +++ b/chapter_16/zvehicle_sales_data_TRANSPOSED.csv @@ -0,0 +1,93 @@ +Make,Model,Type,2005-01,2005-02,2005-03,2005-04,2005-05,2005-06,2005-07,2005-08,2005-09,2005-10,2005-11,2005-12,2006-01,2006-02,2006-03,2006-04,2006-05,2006-06,2006-07,2006-08,2006-09,2006-10,2006-11,2006-12,2007-01,2007-02,2007-03,2007-04,2007-05,2007-06,2007-07,2007-08,2007-09,2007-10,2007-11,2007-12,2008-01,2008-02,2008-03,2008-04,2008-05,2008-06,2008-07,2008-08,2008-09,2008-10,2008-11,2008-12,2009-01,2009-02,2009-03,2009-04,2009-05,2009-06,2009-07,2009-08,2009-09,2009-10,2009-11,2009-12,2010-01,2010-02,2010-03,2010-04,2010-05,2010-06,2010-07,2010-08,2010-09,2010-10,2010-11,2010-12,2011-01,2011-02,2011-03,2011-04,2011-05,2011-06,2011-07,2011-08,2011-09,2011-10,2011-11,2011-12,2012-01,2012-02,2012-03,2012-04,2012-05,2012-06,2012-07,2012-08,2012-09,2012-10,2012-11,2012-12,2013-01,2013-02,2013-03,2013-04,2013-05,2013-06,2013-07,2013-08,2013-09,2013-10,2013-11,2013-12,2014-01,2014-02,2014-03,2014-04,2014-05,2014-06,2014-07,2014-08,2014-09,2014-10,2014-11,2014-12,2015-01,2015-02,2015-03,2015-04,2015-05,2015-06,2015-07,2015-08,2015-09,2015-10,2015-11,2015-12,2016-01,2016-02,2016-03,2016-04,2016-05,2016-06,2016-07,2016-08,2016-09,2016-10,2016-11,2016-12,2017-01,2017-02 +Honda,Insight,HEV,7,22,56,90,52,69,68,80,83,37,60,42,59,72,79,110,92,77,91,109,19,9,2,3,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,569,2096,2780,2079,2295,4226,1746,1739,1403,1639,1307,2014,1652,1880,1913,1491,1858,2030,1679,1965,1536,1637,1554,1722,2782,2644,1435,1021,987,961,512,492,749,690,492,773,1032,738,512,494,419,341,246,251,238,310,319,388,454,391,426,384,420,438,299,463,402,418,317,339,410,441,493,333,291,290,240,222,278,311,223,211,209,183,139,126,113,85,64,53,30,22,19,0,2,9,9,9,5,9,1,0,3,9,1,0 +Toyota,Prius,HEV,5566,7078,10236,11345,9461,9622,9691,9850,8193,9939,7889,9027,7654,6547,7922,8234,8103,9696,11114,11177,10492,8733,8008,9291,8299,12227,19156,13056,24009,17756,16062,14055,12494,13158,16737,14212,11379,10895,20635,21757,15011,11765,14785,13463,10873,11804,8660,7859,8121,7232,8924,8385,10091,12998,19173,18886,10984,13496,9617,11775,8484,7968,11786,12555,14248,10998,14102,11799,11394,11731,10224,15639,10635,13539,18605,12477,6924,4340,7907,9491,9325,11008,15208,17004,11555,20589,27800,23514,20391,18455,15955,20064,17280,14885,14739,18679,14898,17119,21354,19290,22844,20495,22477,25567,14738,13528,15029,14801,11402,11820,17130,16270,24101,17078,19304,22619,13924,13032,13506,13922,11843,11621,15565,14807,18836,14587,17340,17413,15894,15112,12531,15054,9301,10544,12068,11921,12513,11016,12690,12982,12471,8132,9714,10803,6463,7682 +Honda,Civic,HEV,1169,1353,2896,3466,1895,1852,2329,4146,1916,231,2083,2528,3166,1781,2232,3087,2890,2601,2673,3411,2508,2288,2208,2408,1783,1924,2813,2855,4520,3246,2493,2102,2092,2286,3238,3223,1745,1808,3769,4324,4676,2710,3440,3105,2020,1621,1043,1036,1076,1362,2869,3361,2077,1583,969,717,152,239,243,471,253,346,579,621,717,595,617,761,667,662,612,906,653,532,441,121,268,418,311,106,305,480,503,565,449,741,906,766,708,548,471,579,493,453,530,512,429,433,572,569,570,568,578,697,402,1158,1031,712,439,443,338,450,415,410,409,503,360,395,432,476,320,358,351,386,458,391,463,590,613,455,239,263,161,143,166,92,83,62,60,50,38,14,15,12,16,8 +Ford,Escape,HEV,908,1092,1569,1705,1234,1126,1168,1363,1808,1313,1121,1553,898,1341,1590,3420,2862,1884,2060,1789,1651,1602,1484,1968,1238,1696,2523,2275,3214,2526,1578,1833,1652,2084,2224,2265,1474,1743,2008,1907,2378,1912,1265,1338,990,1997,1361,1149,880,1294,1351,1134,1827,1405,2543,2102,878,949,960,1157,715,782,1282,1119,1383,1360,1220,790,842,809,814,972,520,795,1195,1070,1118,826,652,563,566,573,1131,1080,345,434,162,0,206,17,50,34,81,9,21,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Honda,Accord,HEV,805,855,1862,2023,1314,1080,1376,2336,2352,1266,837,720,351,783,581,614,520,396,504,499,389,287,311,363,248,312,385,318,439,342,260,275,229,243,204,150,48,42,53,25,16,7,3,2,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,23,530,426,525,910,1346,1442,1530,1135,1362,1175,1095,1130,1094,1233,805,832,948,1118,1463,1241,1481,1369,854,442,289,223,71,68,51,29,15,31,565,890,1160,1296,1879,3124,1711,1867 +Toyota,Highlander,HEV,,,,,35,2869,2564,2925,2715,2330,2353,2198,2263,2631,2987,3768,3755,2705,2784,2581,2347,1643,1667,2354,1810,1892,2501,2394,3312,2403,1205,378,193,596,2577,2791,2143,1938,2239,2578,2644,1511,1371,1227,921,1022,907,890,984,956,1037,933,1351,1098,1171,836,269,700,722,1029,526,339,594,692,683,611,575,486,523,756,722,949,689,707,797,380,149,74,185,226,218,239,322,563,362,474,607,552,560,496,469,449,413,466,485,588,452,441,477,495,545,550,410,440,325,331,332,272,145,105,333,418,355,280,214,288,303,327,425,428,268,256,295,305,323,311,304,377,367,375,318,516,375,396,492,442,473,528,524,506,383,356,483,1018,571,1339 +Lexus,RX 450h,HEV,,,13,2345,2931,2605,2262,2607,2113,1904,1722,2172,1477,1803,2470,2247,2006,1190,1220,1514,1687,1239,1327,1981,1245,1249,1471,1384,1746,1562,1385,1172,979,1392,1674,2032,1211,1148,1570,1624,2155,1330,1439,1277,744,615,624,1463,1556,1502,1165,655,393,527,1369,1754,1168,1567,1210,1598,1016,890,1251,1232,1358,1304,1356,1370,1112,1402,1293,1535,912,999,1438,1167,610,413,671,841,650,861,928,1233,753,826,992,801,1011,1193,1171,1170,944,997,971,1394,744,756,925,688,885,900,962,1116,815,1258,1105,1153,637,621,852,387,837,872,914,1090,695,728,788,930,521,494,641,492,551,486,530,599,443,514,958,1493,790,752,886,899,719,684,684,574,387,535,666,985,443,507 +Toyota,Camry,HEV,,,,,,,,,,,,,,,,86,3032,4268,5023,4977,4044,2806,3100,4005,2801,3332,5144,4410,6853,5530,4329,4284,4196,3511,5118,4969,3750,4121,6930,6678,5999,3054,2645,3456,2785,2792,2174,1888,1141,2080,2554,2198,2941,2093,2509,2114,872,1407,1465,1513,867,1011,1549,1655,1455,1097,1276,1165,1104,1194,983,1231,860,993,1437,1110,592,449,393,318,229,333,730,1797,2116,3750,5404,4406,4403,3471,3197,3840,3704,2986,3936,4443,3826,4147,4461,3257,4265,3878,4193,4729,3069,2903,2994,2726,1978,2517,4287,3916,5199,3874,4609,4320,1986,2161,2220,2448,2143,2110,2739,2650,3174,2755,2756,3314,2629,2545,1964,1861,1256,1599,1746,1975,2055,1649,2214,2155,1902,1802,1693,2181,1238,1333 +Lexus,GS 450h,HEV,,,,,,,,,,,,,,,,141,294,231,157,192,164,177,176,252,167,160,181,174,181,131,142,130,72,71,100,136,64,77,65,82,98,73,40,35,29,22,42,51,41,22,42,33,43,27,45,48,38,39,37,54,41,22,31,25,38,22,16,15,18,29,18,30,19,33,24,29,18,24,26,17,18,19,22,33,25,20,12,10,42,75,60,94,89,68,60,52,34,38,56,34,39,55,63,69,31,34,25,44,30,23,25,35,9,15,8,13,3,2,9,11,8,10,9,12,8,7,11,4,7,7,5,3,5,5,8,16,7,3,12,3,4,0,1,6,6,5 +Lexus,HS 250h,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,543,1242,1527,1407,1980,1247,712,1494,1076,1360,603,165,594,711,792,788,1121,286,183,230,279,220,159,306,284,231,205,207,274,152,150,261,28,21,10,5,7,8,3,3,2,0,1,1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Nissan,Altima,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,206,462,483,821,804,1131,643,756,927,1191,964,473,529,832,801,1607,1333,715,442,470,554,353,710,644,463,834,222,345,666,1030,3164,345,299,503,842,1059,619,394,330,1167,479,378,284,511,443,434,612,365,366,545,334,499,250,204,318,217,49,55,34,27,22,18,10,9,3,7,0,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Lexus,LS 600hL,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,267,196,175,170,129,105,112,113,122,112,73,83,71,47,55,37,50,33,22,25,19,27,31,28,10,12,21,15,15,9,15,9,7,8,4,14,15,9,9,13,17,8,7,9,10,1,4,6,9,8,9,5,9,8,6,5,8,6,6,1,0,1,5,2,6,14,22,12,15,11,10,6,5,3,6,5,6,11,11,7,9,5,5,6,4,0,2,1,4,5,7,7,5,7,1,5,3,3,1,0,3,3,2,4,5,2,1,2,11,6,0,2,2,0,0 +Saturn,Vue,HEV,,,,,,,,,,,,,,,,,,,,,,,,,793,793,793,793,797,,,,,,,,135,135,135,135,340,277,362,417,443,354,328,338,153,188,362,338,227,239,269,414,90,56,134,186,14,4,8,4,3,14,0,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Chevrolet,Tahoe,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,233,234,234,234,589,547,351,798,1101,795,767,1729,599,632,609,523,641,547,538,562,615,792,489,645,278,315,368,399,565,368,262,252,215,245,213,377,217,191,278,276,229,129,115,76,31,88,79,168,76,151,227,144,161,124,132,135,110,146,171,224,97,91,109,116,154,120,58,83,45,55,51,57,21,12,26,14,14,21,6,7,2,5,6,3,3,8,1,4,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Chevrolet,Malibu,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,112,112,112,112,282,295,349,388,382,325,195,454,145,197,547,547,706,489,476,441,156,114,212,132,67,68,80,67,41,36,14,12,2,6,7,5,0,0,0,0,2,22,0,0,0,0,0,0,1,350,1416,1557,1642,2002,1938,2414,1656,1266,1041,1381,981,1254,1359,1551,1695,1651,1338,1582,858,819,425,266,232,202,191,130,94,62,30,21,10,17,14,15,6,8,8,4,2,27,1,0,1,1,0,1,0,0,2,1,246,371,416,522,618,600,769,790,339,534 +Saturn,Aura,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,14,14,14,15,36,30,29,26,31,22,45,34,19,23,26,31,35,56,24,65,30,30,29,159,25,2,4,0,2,5,4,3,1,4,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Dodge,Durango,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,46,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Chevrolet,Silverado,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,47,68,95,130,123,180,226,120,167,156,279,97,106,180,161,337,120,135,379,232,391,97,158,213,67,120,119,111,90,37,23,82,53,45,205,25,54,94,42,62,38,48,96,29,72,188,192,19,21,18,27,20,13,10,13,6,9,7,6,1,3,1,3,4,9,1,1,1,1,4,1,2,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 +Ford,Fusion,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,451,1165,2079,2244,2810,2593,1260,1333,1401,1686,1152,1317,1784,1607,2562,2103,1676,3104,1756,1816,1586,1769,969,1379,1466,1285,1256,969,456,216,552,857,993,888,611,1110,1009,778,683,797,1109,1071,898,956,1834,3244,3043,3806,3417,3625,3335,3057,2914,3694,2265,2577,2769,2768,2607,3096,3903,3537,4641,3016,2851,2943,1972,2164,2323,2372,1782,2416,2534,1820,2440,1691,2157,2441,2002,2050,1388,1960,1373,1764,2057,2035,1716,2542,3519,3002,3776,4915,3372,3577,4856,4939 +Mercedes-Benz,S400,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,77,77,98,108,101,63,69,84,83,114,39,42,26,24,25,32,49,26,25,15,22,9,19,37,11,28,10,8,7,8,5,11,9,10,4,10,12,9,8,7,8,5,8,2,0,0,3,2,1,2,1,0,0,0,0,0,1,0,1,4,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Mercedes-Benz,ML450,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,70,69,67,37,181,212,24,79,24,2,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,3,2,2,2,0,0,0,3,6,0,0,0,0,2,0,0,0,0,0,1,2,0,0,7,0,0,0,0,0,0,10,0,0,2,2,0,5,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Mercedes-Benz,E320,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Mazda,Tribute,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,43,42,59,58,61,55,68,55,53,67,46,48,36,37,34,37,35,64,48,51,32,38,36,36,24,21,29,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BMW,X6,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,22,21,21,21,12,128,3,3,2,0,9,6,5,9,5,2,3,6,5,0,4,2,-1,3,0,0,2,-1,1,1,1,0,0,-1,2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BMW,Activehybrid3&5&7,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,11,9,26,9,7,8,25,32,35,38,32,38,27,20,15,16,9,25,51,31,60,54,29,26,9,21,25,40,321,214,206,77,133,133,223,138,134,129,95,59,85,106,144,34,39,43,25,30,37,16,16,32,9,10,17,7,1,11,3,7,8,6,3,2,0,4,11,2,0,1,2,8,0,3,0,7,23,18,0,0,0 +Honda,CR-z,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,694,1236,1419,1024,876,894,1091,1685,1819,1557,966,878,745,537,289,305,564,363,466,536,334,296,409,330,392,335,244,244,243,358,381,451,405,427,393,384,483,264,325,295,384,267,318,354,369,389,302,356,342,248,205,188,224,196,175,255,216,246,204,270,333,310,316,236,316,192,128,163,253,234,235,272,222,165,168,146,160,89,118 +Lincoln,MKZ,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,366,392,424,370,395,615,503,561,483,480,491,455,477,475,434,253,419,626,397,480,451,594,998,781,465,282,321,100,177,446,884,715,768,646,791,619,717,852,754,726,919,1411,1047,1128,787,638,758,645,662,569,743,468,480,717,810,1005,700,725,713,596,646,676,867,491,585,608,613,805,766,681,541,460,450,552,667,467,570 +Porsche,Cayenne,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,206,211,142,114,107,114,177,130,128,112,107,140,89,112,137,124,104,150,42,60,69,84,106,108,84,60,32,46,46,48,62,39,43,67,59,58,55,45,64,96,84,75,72,159,14,13,18,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Lexus,CT 200h,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2199,875,454,240,1553,2087,1444,1511,1759,2259,1025,1640,2223,1620,1549,1387,1499,1472,1195,1199,1264,1598,1001,1182,1062,1171,1623,1513,1306,1784,798,842,1002,1787,1290,1230,1480,1054,1762,1521,1979,2191,1078,1158,1322,1608,1005,978,1416,1170,1436,1118,1374,1504,1131,1077,984,1464,622,762,972,577,797,785,849,819,638,564,550,968,393,458 +Volkswagen,Touareg,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,65,60,44,52,40,23,14,10,14,18,21,29,36,18,19,12,18,25,27,17,5,11,44,18,21,43,12,7,6,12,3,7,3,1,1,2,3,0,4,3,3,6,2,4,1,1,1,2,2,1,3,0,6,2,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 +Infinity,Q70 (M35h),HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,42,36,33,35,54,45,33,46,54,35,58,47,23,78,73,59,60,45,66,71,76,37,46,58,35,42,47,33,44,33,34,33,33,44,14,19,11,12,11,8,5,6,13,17,20,19,14,22,15,14,12,11,13,12,14,14,16,10,10,12,11,10,10,10,9,8,9,7,12,5,4 +Hyundai,Sonata,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1422,4177,4136,2000,2001,1723,1907,1304,1568,2095,1847,1869,1884,1888,1766,1560,1510,1589,1874,1192,1441,1623,1447,1817,2129,2200,2303,2102,1318,1866,2121,1340,1907,2430,2055,2094,1523,2800,1910,2134,1181,781,897,672,1605,1793,2481,2943,2334,1837,1647,1185,1342,931,1138,964,1588,1884,1788,2513,1242,1301,1146,1815,1479,1867,1374,1113,1471 +Buick,LaCrosse,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,297,522,982,781,1248,1117,1165,1202,1245,867,1024,840,978,724,819,576,706,717,662,668,619,530,803,423,552,430,447,445,506,536,716,772,610,462,545,587,704,772,698,326,514,497,531,498,341,322,275,200,199,194,145,118,87,83,115,42,60,55,60,35,53,31,26,18,12 +Buick,Regal,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,86,63,137,135,130,174,219,233,331,463,287,211,181,184,375,387,389,291,227,183,214,185,178,187,93,78,88,95,41,64,75,34,47,32,40,46,22,12,20,21,28,23,17,8,16,13,11,9,8,3,7,7,14,7,4,2,0,0,0,0,1,3,0 +Porsche,Panamera S,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,26,26,39,34,43,26,73,25,35,48,86,48,67,46,46,5,11,5,7,4,29,0,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Kia,Optima,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,705,925,1201,837,810,933,848,907,902,745,681,751,909,1215,1001,1000,1206,1100,1241,1601,1272,1151,1233,990,777,960,1879,1060,735,1006,1155,1318,1003,1483,1101,1299,844,856,805,892,1046,897,873,1167,1136,1262,844,870,469,386,436,483,570,483,768,654,591,482,423,397,279,257 +Acura,ILX,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,34,115,110,136,140,144,174,119,84,154,145,152,195,163,110,125,108,137,44,44,27,42,46,49,63,44,35,24,15,15,10,9,3,5,4,2,4,1,0,0,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,,0, +Ford,C-Max,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,969,3038,3589,3339,2387,2849,3275,3197,3261,2889,2267,2411,1424,1438,1457,1201,947,1301,1685,1586,2051,1952,2163,2451,1109,1318,1296,1303,765,878,1054,1237,1892,1814,1225,1501,1247,912,815,837,637,880,1092,1621,1327,1486,1112,879,739,398,811,895,473,676 +Lexus,ES Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,817,1400,1520,1424,1866,1324,1154,1561,1237,1434,1239,1324,1600,1223,1367,1393,1706,866,945,1384,1242,1408,1102,1358,1628,1128,1182,1194,1400,746,758,1076,789,911,711,891,1281,907,895,833,1443,622,633,894,700,735,646,705,692,497,353,434,734,242,330 +Audi,Q5 Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,33,90,122,90,76,84,86,105,83,47,73,73,56,38,43,36,24,35,21,25,19,22,31,19,24,16,11,8,10,9,7,17,5,8,5,3,5,7,13,3,0,5,2,2,2,1,2,1,0,0,0,0,0 +Toyota,Avalon,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,747,1040,1361,1616,1423,1514,1394,1139,1467,1104,1398,1532,1480,970,613,1600,1522,1957,1437,1767,2049,1437,1330,1212,1154,912,864,902,906,1114,973,1175,1322,1064,993,798,933,583,590,776,715,660,619,707,775,688,673,639,1026,448,464 +Volkswagen,Jetta,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,162,232,272,451,353,473,438,417,712,887,666,394,360,224,232,276,149,209,206,156,151,114,97,68,57,50,36,45,41,55,66,91,98,77,64,52,65,46,39,47,46,47,44,87,128,76,48,45,56,13,12 +Mercedes-Benz,E400H,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,22,22,25,17,29,23,26,29,27,22,20,20,23,15,9,39,16,13,5,7,12,5,5,9,30,3,13,0,2,0,2,2,0,1,0,0,1,0,1,0,1,4,2,1,2,0,2,0,1,0 +Infiniti,Q50,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,47,51,118,91,59,328,380,263,294,242,246,266,274,296,422,386,297,365,390,299,342,347,381,384,356,381,189,281,175,202,335,147,95,94,112,150,174,148,134,232,128,138 +Chevrolet,Impala Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,16,35,34,38,49,34,58,63,43,63,35,32,23,93,19,19,29,49,53,24,23,27,5,11,1,12,12,4,4,3,2,10,0,0,0,0,0,0,0,0 +Infiniti,QX60,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,302,374,238,135,167,114,137,108,112,130,109,114,146,168,129,179,195,170,188,180,226,240,231,220,149,249,119,137,195,66,85,88,74,65,63,59,64,99,44,53 +Nissan,Pathfinder Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,334,265,191,237,183,238,191,221,237,160,166,187,204,184,212,258,167,223,215,234,212,186,168,102,84,65,72,87,56,60,57,55,58,80,64,68,94,73,90 +Subaru,XV,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,470,546,725,711,1003,788,746,747,571,617,575,427,512,549,587,552,557,493,559,455,370,211,319,425,261,278,329,303,303,214,193,117,79,44,27,25,13,6 +Acura,RLX,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,31,36,37,29,14,21,18,15,24,27,28,34,26,14,13,16,0,12,19,19,18,0,11,19,24,13,33,31,11,27 +Lexus,NX Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,354,163,164,225,210,250,203,234,206,170,188,196,364,245,236,251,222,229,183,228,224,233,188,241,362,179,184 +Toyota,RAV4,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,64,1430,1973,2462,3073,3807,4185,3751,4692,4919,4127,3551,3757,4773,2898,3080 +Acura,NSX,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,21,22,38,67,51,68,50,46 +Kia,Niro Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,42,2143 +Hyundai,Ioniq Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,1 +Chevrolet,Volt,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,326,321,281,608,493,481,561,125,302,723,1108,1139,1529,603,1023,2289,1462,1680,1760,1849,2831,2851,2961,1519,2633,1140,1626,1478,1306,1607,2698,1788,3351,1766,2022,1920,2392,918,1210,1478,1548,1684,1777,2020,2511,1394,1439,1336,1490,542,693,639,905,1618,1225,1313,1380,949,2035,1980,2114,996,1126,1865,1983,1901,1937,2406,2081,2031,2191,2531,3691,1611,1820 +Prius,PHEV,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,911,1654,1086,695,688,1047,1652,1889,1766,1361,874,693,786,599,678,584,817,1791,1152,2095,1100,919,803,1041,1452,1741,2692,1571,1371,818,353,479,451,492,401,397,473,428,727,464,584,344,216,91,44,22,10,6,7,4,4,11,4,2,4,0,781,1641,1366,1362 +Ford,C-Max Energi,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,144,1259,971,338,334,494,411,450,455,433,621,758,1092,941,827,471,552,610,525,782,988,831,1050,677,644,644,659,395,498,715,553,715,667,693,723,719,695,639,579,350,490,610,607,538,630,755,707,689,571,721,1289,473,639 +Honda,Accord,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,17,26,55,58,42,54,44,51,71,68,38,27,24,18,37,46,28,41,46,42,34,43,63,28,12,5,5,5,4,1,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Ford,Fusion Energi,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,119,295,364,416,390,407,600,750,1087,870,791,533,779,899,743,1342,1939,1226,1222,640,686,752,789,426,603,837,711,986,727,852,949,808,849,944,1058,581,932,1238,1331,1453,1700,1341,1422,1652,1372,1817,1099,606,837 +Porsche,Panamera S E-Hybrid,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,47,141,57,56,63,53,111,63,68,82,97,57,31,61,40,44,30,21,34,23,36,41,28,33,16,27,33,23,25,26,22,21,59,28,38,88,3,2,1 +Cadillac,ELR,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,6,41,58,81,61,52,97,188,196,111,152,155,118,92,127,92,104,116,62,66,45,36,82,67,135,67,91,104,95,45,94,15,6,6,3,5,3,3,0 +BMW,i8,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,58,204,126,158,85,113,143,138,117,137,217,210,182,149,118,656,32,54,89,130,146,169,166,145,158,199,173,133,50,58 +Porsche,Cayenne S E-hybrid,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,67,83,106,72,88,111,89,77,83,70,126,121,137,146,172,244,237,191,176,148,197,131,138,179,152,177,121 +Mercedes-Benz,S550 Plug,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,17,25,21,35,19,36,12,29,27,27,32,30,41,174,52,71,55,51 +Volvo,XC90 Plug In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,0,1,7,74,226,176,178,150,110,166,178,176,148,142,161,204,96,83 +BMW,X5,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,285,607,181,345,313,655,500,583,649,876,482,406,436,569,262,275 +Hyundai,Sonata Plug In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,15,0,175,200,275,250,250,200,350,250,275,250,275,250,150,250 +Audi,A3 Plug In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,327,248,332,321,361,353,349,346,312,348,394,589,387,400 +BMW,3-series Plug-In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,29,25,67,26,81,51,54,92,215,240,129,144 +Mercedes-Benz,GLE 550e,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,30,24,26,19,30,83,52,59 +BMW,7-series Plug-in,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,23,18,35 +Mercedes-Benz,C350We,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,171,210,51 +Kia,Optima Plug-in,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,40,61 +Nissan,LEAF,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,87,67,298,573,1142,1708,931,1362,1031,849,672,954,676,478,579,370,510,535,395,685,984,1579,1539,1489,650,653,2236,1937,2138,2225,1864,2420,1953,2002,2003,2529,1252,1425,2507,2088,3117,2347,3019,3186,2881,2589,2687,3102,1070,1198,1817,1553,2104,2074,1174,1393,1247,1238,1054,1347,755,930,1246,787,979,1096,1063,1066,1316,1412,1457,1899,772,1037 +Smart,ED,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,16,16,0,0,8,0,1,1,0,17,101,182,0,2,0,0,0,127,6,1,0,0,3,0,1,1,0,0,60,53,58,182,137,111,153,167,97,122,186,203,206,278,298,208,182,150,313,351,147,76,103,124,102,94,109,106,94,75,178,179,48,54,70,66,75,53,62,55,44,43,47,40,15,22 +Mitsubishi,I EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,76,36,44,56,79,85,33,33,37,36,30,42,77,257,337,31,127,91,39,46,30,20,28,12,11,1,3,24,12,35,22,17,20,15,17,18,12,3,2,10,16,18,23,12,6,3,9,4,9,2,5,1,6,2,4,20,25,17,4,5,3,0,1 +BMW,Active E,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,112,115,326,30,11,79,0,0,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Ford,Focus,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,89,38,34,59,118,172,167,81,158,180,147,157,177,150,175,110,115,130,158,100,129,177,116,177,197,198,264,176,186,191,53,85,145,140,124,165,152,135,176,145,126,93,96,66,81,110,81,54,54,58,75,82,73,66,101,56,228 +Honda,Fit EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,9,16,16,26,19,8,15,23,22,15,208,63,66,35,40,23,51,30,33,37,50,33,38,42,55,29,23,5,32,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Tesla,Model S,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,150,450,800,900,1350,1450,1950,2100,2000,1800,1550,1700,1100,1300,1400,1700,1300,1400,1300,1400,1400,1400,1400,1200,1300,1300,1450,1900,1300,1400,2000,1900,2300,2800,1800,1600,2400,2100,3100,3500,1300,1900,3000,1700,1500,2800,2400,3200,4100,1200,1800,5300,1200,1700 +Toyota,RAV4 EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,47,32,52,25,52,133,70,84,44,109,231,167,0,62,28,63,101,73,69,149,91,68,228,125,97,83,37,7,2,4,4,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Chevrolet,Spark,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,27,103,102,78,87,87,76,93,71,108,97,182,85,128,80,51,58,61,131,86,119,151,920,283,226,57,135,157,177,166,152,139,216,252,419,394,359,333,292,315,260,39,17,4,4 +Fiat,500E,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,50,50,50,60,50,35,40,166,152,167,166,119,166,137,140,100,115,119,117,164,450,471,411,353,370,347,231,174,270,217,195,373,372,388,278,274,311,370,319,287,353,305,283 +BMW,i3,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,336,358,363,1025,1022,1159,816,1013,670,1089,922,406,818,551,935,792,1710,986,723,1422,182,248,332,814,696,608,1479,1013,391,442,629,791,382,318 +Mercedes-Benz,B-Class,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,41,51,65,98,193,326,240,109,145,158,278,242,196,172,147,81,41,97,58,37,66,56,49,44,50,57,51,58,52,54,53,56 +Volkswagen,e-Golf,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,119,237,181,130,195,309,410,293,313,381,343,596,472,609,328,198,86,326,269,248,344,454,529,407,305,443,332,293 +Kia,Soul EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,109,140,110,69,48,63,73,108,109,59,93,105,109,83,96,81,60,79,139,120,134,179,153,217,190,179,197,117,152 +Tesla,Model X,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,10,15,177,400,500,1500,1500,2000,2000,1500,1900,2600,1000,1400,3300,1000,800 +Chevrolet,Bolt,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,579,1162,952 +Hyundai,Tucson,FCEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,10,10,6,1,10,12,6,3,3,1,2,2,0,1,5,1,0,0,2,3,4,4,4,8,8,2,4,0,0,1,2,5 +Toyota,Mirai,FCEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,0,2,38,23,15,26,30,41,41,40,40,52,371,69,103,105,116,83,110 +Honda,Clarity,FCEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,42,27 \ No newline at end of file From bb799f5134e95e5d8af415747c92e9526890611b Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 17 Apr 2017 13:57:04 -0700 Subject: [PATCH 62/85] Minor indent fix --- chapter_16/01_initial_chart.html | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/chapter_16/01_initial_chart.html b/chapter_16/01_initial_chart.html index f4f0eac..bed750b 100644 --- a/chapter_16/01_initial_chart.html +++ b/chapter_16/01_initial_chart.html @@ -130,29 +130,29 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005&nda //Create scale functions xScale = d3.scaleTime() - .domain([ - d3.min(dataset, function(d) { return d.date; }), - d3.max(dataset, function(d) { return d.date; }) - ]) - .range([padding, w - padding * 2]); + .domain([ + d3.min(dataset, function(d) { return d.date; }), + d3.max(dataset, function(d) { return d.date; }) + ]) + .range([padding, w - padding * 2]); yScale = d3.scaleLinear() - .domain([ - 0, - d3.max(dataset, function(d) { - var sum = 0; - - //Loops once for each row, to calculate - //the total (sum) of sales of all vehicles - for (var i = 0; i < keys.length; i++) { - sum += d[keys[i]].sales; - }; - - return sum; - }) - ]) - .range([h - padding, padding / 2]) - .nice(); + .domain([ + 0, + d3.max(dataset, function(d) { + var sum = 0; + + //Loops once for each row, to calculate + //the total (sum) of sales of all vehicles + for (var i = 0; i < keys.length; i++) { + sum += d[keys[i]].sales; + }; + + return sum; + }) + ]) + .range([h - padding, padding / 2]) + .nice(); //Define axes xAxis = d3.axisBottom() From cd48d713db153c129aaac2af7a7b4c0f686d7ee6 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 17 Apr 2017 15:05:53 -0700 Subject: [PATCH 63/85] More ch 16 examples --- chapter_16/02_color_by_type.html | 238 ++++++++++++++++++++++++++++++ chapter_16/03_sorted_by_type.html | 238 ++++++++++++++++++++++++++++++ chapter_16/04_types_only.html | 238 ++++++++++++++++++++++++++++++ 3 files changed, 714 insertions(+) create mode 100644 chapter_16/02_color_by_type.html create mode 100644 chapter_16/03_sorted_by_type.html create mode 100644 chapter_16/04_types_only.html diff --git a/chapter_16/02_color_by_type.html b/chapter_16/02_color_by_type.html new file mode 100644 index 0000000..f4eafe3 --- /dev/null +++ b/chapter_16/02_color_by_type.html @@ -0,0 +1,238 @@ + + + + + D3: Vehicles, colored by type + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file diff --git a/chapter_16/03_sorted_by_type.html b/chapter_16/03_sorted_by_type.html new file mode 100644 index 0000000..653891c --- /dev/null +++ b/chapter_16/03_sorted_by_type.html @@ -0,0 +1,238 @@ + + + + + D3: Vehicles, sorted by type + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file diff --git a/chapter_16/04_types_only.html b/chapter_16/04_types_only.html new file mode 100644 index 0000000..dfe1803 --- /dev/null +++ b/chapter_16/04_types_only.html @@ -0,0 +1,238 @@ + + + + + D3: Types only + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file From 614bdb02cf58deb6cc05709277105771d63ce542 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 17 Apr 2017 15:42:17 -0700 Subject: [PATCH 64/85] Ch 16 example progress --- chapter_16/01_initial_chart.html | 2 +- chapter_16/02_color_by_type.html | 2 +- chapter_16/03_sorted_by_type.html | 2 +- chapter_16/04_types_only.html | 133 +++++++++++++++++++++++++++--- 4 files changed, 126 insertions(+), 13 deletions(-) diff --git a/chapter_16/01_initial_chart.html b/chapter_16/01_initial_chart.html index bed750b..759ecb6 100644 --- a/chapter_16/01_initial_chart.html +++ b/chapter_16/01_initial_chart.html @@ -67,7 +67,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005&nda //Create a new object dataset[i - 3] = { - date: parseTime(rows[i][0]), //Make a new Date object for each year + month + date: parseTime(rows[i][0]) //Make a new Date object for each year + month }; //Loop once for each vehicle in this row (i.e., for this date) diff --git a/chapter_16/02_color_by_type.html b/chapter_16/02_color_by_type.html index f4eafe3..caeca50 100644 --- a/chapter_16/02_color_by_type.html +++ b/chapter_16/02_color_by_type.html @@ -67,7 +67,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Create a new object dataset[i - 3] = { - date: parseTime(rows[i][0]), //Make a new Date object for each year + month + date: parseTime(rows[i][0]) //Make a new Date object for each year + month }; //Loop once for each vehicle in this row (i.e., for this date) diff --git a/chapter_16/03_sorted_by_type.html b/chapter_16/03_sorted_by_type.html index 653891c..2d070b0 100644 --- a/chapter_16/03_sorted_by_type.html +++ b/chapter_16/03_sorted_by_type.html @@ -67,7 +67,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Create a new object dataset[i - 3] = { - date: parseTime(rows[i][0]), //Make a new Date object for each year + month + date: parseTime(rows[i][0]) //Make a new Date object for each year + month }; //Loop once for each vehicle in this row (i.e., for this date) diff --git a/chapter_16/04_types_only.html b/chapter_16/04_types_only.html index dfe1803..78dc5b6 100644 --- a/chapter_16/04_types_only.html +++ b/chapter_16/04_types_only.html @@ -39,9 +39,9 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //For converting Dates to strings var formatTime = d3.timeFormat("%b %Y"); - //Set up stack method - var stack = d3.stack(); - //.order(d3.stackOrderDescending); // <-- Flipped stacking order + //Set up stack methods + var vehicleStack = d3.stack(); + var typeStack = d3.stack(); //Load in data d3.request("vehicle_sales_data.csv") @@ -67,7 +67,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Create a new object dataset[i - 3] = { - date: parseTime(rows[i][0]), //Make a new Date object for each year + month + date: parseTime(rows[i][0]) //Make a new Date object for each year + month }; //Loop once for each vehicle in this row (i.e., for this date) @@ -113,17 +113,78 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar // console.log(keys); //Tell stack function where to find the keys - stack.keys(keys) + vehicleStack.keys(keys) .value(function value(d, key) { return d[key].sales; }); //Stack the data and log it out - var series = stack(dataset); - // console.log(series); + var vehicleSeries = vehicleStack(dataset); + // console.log(vehicleSeries); + + // + // TYPE DATA SERIES + // + //The goal here is to make a totally separate data set that + //includes just monthly totals for each `type` (HEV, PHEV, BEV, FCEV). + + //Make typeDataset an empty array, so we can start adding values + typeDataset = []; + + //Loop once for each row of the CSV, starting at row 3, + //since rows 0-2 contain only vehicle info, not sales values. + for (var i = 3; i < rows.length; i++) { + + //Create a new object + typeDataset[i - 3] = { + date: parseTime(rows[i][0]), //Make a new Date object for each year + month + "HEV": 0, + "PHEV": 0, + "BEV": 0, + "FCEV": 0 + }; + + //Loop once for each vehicle in this row (i.e., for this date) + for (var j = 1; j < rows[i].length; j++) { + + var type = rows[2][j]; //'Type' from 3rd row in CSV + var sales = rows[i][j]; //Sales value for this vehicle and month + + //If sales value exists… + if (sales) { + sales = parseInt(sales); //Convert from string to int + } else { //Otherwise… + sales = 0; //Set to zero + } + + //Add sales value to existing sum + typeDataset[i - 3][type] += sales; + + } + + } + + //Log out the final state of dataset + // console.log(typeDataset); + + + + // + // STACKING + // + + //Tell stack function where to find the keys + typeStack.keys([ "HEV", "PHEV", "BEV", "FCEV" ]); + + //Stack the data and log it out + var typeSeries = typeStack(typeDataset); + // console.log(typeSeries); + + + // // MAKE THE CHART // @@ -177,9 +238,11 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar .attr("width", w) .attr("height", h); - //Create areas - svg.selectAll("path") - .data(series) + //Create areas for individual VEHICLES + svg.append("g") + .attr("id", "vehicles") + .selectAll("path") + .data(vehicleSeries) .enter() .append("path") .attr("class", "area") @@ -217,6 +280,56 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar .text(function(d) { return d.key; }); + + //Create areas for TYPES + svg.append("g") + .attr("id", "types") + .selectAll("path") + .data(typeSeries) + .enter() + .append("path") + .attr("class", "area") + .attr("d", area) + .attr("fill", function(d) { + + //Which type is this? + var thisType = d.key; + + //New color var + var color; + + switch (thisType) { + case "HEV": + color = d3.schemeCategory20[0]; + break; + case "PHEV": + color = d3.schemeCategory20[1]; + break; + case "BEV": + color = d3.schemeCategory20[2]; + break; + case "FCEV": + color = d3.schemeCategory20[3]; + break; + } + + return color; + }) + .append("title") //Make tooltip + .text(function(d) { + return d.key; + }); + + //Click to fade out types + d3.select("g#types") + .on("click", function() { + d3.select(this) + .attr("opacity", 1) + .transition() + .duration(2000) + .attr("opacity", 0); + }); + //Create axes svg.append("g") From f6bf566b3838fc0e0bc9863985537e2f7beee5ff Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 17 Apr 2017 21:22:56 -0700 Subject: [PATCH 65/85] Ch 16 example progress --- chapter_16/04_types_only.html | 10 +- chapter_16/05_click_transitions.html | 353 +++++++++++++++++++++++++++ 2 files changed, 358 insertions(+), 5 deletions(-) create mode 100644 chapter_16/05_click_transitions.html diff --git a/chapter_16/04_types_only.html b/chapter_16/04_types_only.html index 78dc5b6..7fa435b 100644 --- a/chapter_16/04_types_only.html +++ b/chapter_16/04_types_only.html @@ -297,19 +297,19 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //New color var var color; - + switch (thisType) { case "HEV": - color = d3.schemeCategory20[0]; + color = "rgb(110, 64, 170)"; break; case "PHEV": - color = d3.schemeCategory20[1]; + color = "rgb(76, 110, 219)"; break; case "BEV": - color = d3.schemeCategory20[2]; + color = "rgb(35, 171, 216)"; break; case "FCEV": - color = d3.schemeCategory20[3]; + color = "rgb(29, 223, 163)"; break; } diff --git a/chapter_16/05_click_transitions.html b/chapter_16/05_click_transitions.html new file mode 100644 index 0000000..fa12fa7 --- /dev/null +++ b/chapter_16/05_click_transitions.html @@ -0,0 +1,353 @@ + + + + + D3: Click to transition + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file From b26a11ad9a57196a9318b92dae0d652278cd712f Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 18 Apr 2017 11:01:23 -0700 Subject: [PATCH 66/85] Ch 16 example progress --- chapter_16/01_initial_chart.html | 4 +- chapter_16/02_color_by_type.html | 4 +- chapter_16/03_sorted_by_type.html | 4 +- chapter_16/04_types_only.html | 4 +- ...nsitions.html => 05_click_transition.html} | 78 +++- chapter_16/06_update_axis.html | 414 ++++++++++++++++++ 6 files changed, 487 insertions(+), 21 deletions(-) rename chapter_16/{05_click_transitions.html => 05_click_transition.html} (79%) create mode 100644 chapter_16/06_update_axis.html diff --git a/chapter_16/01_initial_chart.html b/chapter_16/01_initial_chart.html index 759ecb6..5821bfb 100644 --- a/chapter_16/01_initial_chart.html +++ b/chapter_16/01_initial_chart.html @@ -194,12 +194,12 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005&nda //Create axes svg.append("g") - .attr("class", "axis") + .attr("class", "axis x") .attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); svg.append("g") - .attr("class", "axis") + .attr("class", "axis y") .attr("transform", "translate(" + (w - padding * 2) + ",0)") .call(yAxis); diff --git a/chapter_16/02_color_by_type.html b/chapter_16/02_color_by_type.html index caeca50..a56824b 100644 --- a/chapter_16/02_color_by_type.html +++ b/chapter_16/02_color_by_type.html @@ -220,12 +220,12 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Create axes svg.append("g") - .attr("class", "axis") + .attr("class", "axis x") .attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); svg.append("g") - .attr("class", "axis") + .attr("class", "axis y") .attr("transform", "translate(" + (w - padding * 2) + ",0)") .call(yAxis); diff --git a/chapter_16/03_sorted_by_type.html b/chapter_16/03_sorted_by_type.html index 2d070b0..2e3df6d 100644 --- a/chapter_16/03_sorted_by_type.html +++ b/chapter_16/03_sorted_by_type.html @@ -220,12 +220,12 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Create axes svg.append("g") - .attr("class", "axis") + .attr("class", "axis x") .attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); svg.append("g") - .attr("class", "axis") + .attr("class", "axis y") .attr("transform", "translate(" + (w - padding * 2) + ",0)") .call(yAxis); diff --git a/chapter_16/04_types_only.html b/chapter_16/04_types_only.html index 7fa435b..28f26bd 100644 --- a/chapter_16/04_types_only.html +++ b/chapter_16/04_types_only.html @@ -333,12 +333,12 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Create axes svg.append("g") - .attr("class", "axis") + .attr("class", "axis x") .attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); svg.append("g") - .attr("class", "axis") + .attr("class", "axis y") .attr("transform", "translate(" + (w - padding * 2) + ",0)") .call(yAxis); diff --git a/chapter_16/05_click_transitions.html b/chapter_16/05_click_transition.html similarity index 79% rename from chapter_16/05_click_transitions.html rename to chapter_16/05_click_transition.html index fa12fa7..1800e78 100644 --- a/chapter_16/05_click_transitions.html +++ b/chapter_16/05_click_transition.html @@ -38,6 +38,11 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //For converting Dates to strings var formatTime = d3.timeFormat("%b %Y"); + + //Define key function, to be used when binding data + var key = function(d) { + return d.key; + }; //Set up stack methods var vehicleStack = d3.stack(); @@ -242,7 +247,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar svg.append("g") .attr("id", "vehicles") .selectAll("path") - .data(vehicleSeries) + .data(vehicleSeries, key) .enter() .append("path") .attr("class", "area") @@ -285,7 +290,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar svg.append("g") .attr("id", "types") .selectAll("path") - .data(typeSeries) + .data(typeSeries, key) .enter() .append("path") .attr("class", "area") @@ -315,17 +320,64 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar return color; }) - .on("click", function() { + .on("click", function(d) { + + //Which type was clicked? + var thisType = d.key; - // d3.select("#types") - // .selectAll("path") - // .attr("opacity", 1) - // .transition() - // .duration(500) - // .attr("opacity", 0); + //Generate a new data set with all-zero values, + //except for this type's data + var thisTypeDataset = []; + + for (var i = 0; i < typeDataset.length; i++) { + thisTypeDataset[i] = { + date: typeDataset[i].date, + HEV: 0, + PHEV: 0, + BEV: 0, + FCEV: 0, + [thisType]: typeDataset[i][thisType] //Overwrites the appropriate zero value above + } + } - d3.select(this) - .attr("opacity", 1); + // console.log(thisTypeDataset); + + //Stack the data (even though there's now just one "layer") and log it out + var thisTypeSeries = typeStack(thisTypeDataset); + // console.log(thisTypeSeries); + + //Bind the new data set to paths, overwriting old bound data. + var paths = d3.selectAll("#types path") + .data(thisTypeSeries, key); + + //Transition areas into new positions (i.e., thisType's area + //will go to a zero baseline; all others will flatten out). + // + //Store this transition in a new variable for later reference. + var areaTransitions = paths.transition() + .duration(1000) + .attr("d", area); + + //Update scale + yScale.domain([ + 0, + d3.max(thisTypeDataset, function(d) { + var sum = 0; + + //Calculate the total (sum) of sales of this type, + //ignoring the others (for now) + sum += d[thisType]; + + return sum; + }) + ]); + + //Append this transition to the one already in progress + //(from above). Transition areas to newly updated scale. + areaTransitions.transition() + .delay(200) + .duration(1000) + .attr("d", area); }) .append("title") //Make tooltip @@ -335,12 +387,12 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Create axes svg.append("g") - .attr("class", "axis") + .attr("class", "axis x") .attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); svg.append("g") - .attr("class", "axis") + .attr("class", "axis y") .attr("transform", "translate(" + (w - padding * 2) + ",0)") .call(yAxis); diff --git a/chapter_16/06_update_axis.html b/chapter_16/06_update_axis.html new file mode 100644 index 0000000..b533f34 --- /dev/null +++ b/chapter_16/06_update_axis.html @@ -0,0 +1,414 @@ + + + + + D3: Update axis + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file From 110a28fbb64de4f731fbf72a7684153c708b96bf Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 18 Apr 2017 21:41:44 -0700 Subject: [PATCH 67/85] Ch 16 example progress --- chapter_16/06_update_axis.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapter_16/06_update_axis.html b/chapter_16/06_update_axis.html index b533f34..e738d27 100644 --- a/chapter_16/06_update_axis.html +++ b/chapter_16/06_update_axis.html @@ -378,7 +378,7 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar .delay(200) .on("start", function() { - //Transition axis to new scale at the same time + //Transition axis to new scale concurrently d3.select("g.axis.y") .transition() .duration(1000) From d91762e9f881149466d38296d4bf6632cd2c911c Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 20 Apr 2017 11:05:56 -0700 Subject: [PATCH 68/85] Ch 16 example progress --- chapter_16/04_types_only.html | 76 ++-- chapter_16/05_click_transition.html | 190 +++++----- chapter_16/06_update_axis.html | 208 +++++------ chapter_16/07_hide_reveal_vehicles.html | 463 ++++++++++++++++++++++++ chapter_16/08_zoom_to_vehicle.html | 463 ++++++++++++++++++++++++ 5 files changed, 1163 insertions(+), 237 deletions(-) create mode 100644 chapter_16/07_hide_reveal_vehicles.html create mode 100644 chapter_16/08_zoom_to_vehicle.html diff --git a/chapter_16/04_types_only.html b/chapter_16/04_types_only.html index 28f26bd..728f3e7 100644 --- a/chapter_16/04_types_only.html +++ b/chapter_16/04_types_only.html @@ -281,44 +281,44 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar return d.key; }); - //Create areas for TYPES - svg.append("g") - .attr("id", "types") - .selectAll("path") - .data(typeSeries) - .enter() - .append("path") - .attr("class", "area") - .attr("d", area) - .attr("fill", function(d) { - - //Which type is this? - var thisType = d.key; - - //New color var - var color; - - switch (thisType) { - case "HEV": - color = "rgb(110, 64, 170)"; - break; - case "PHEV": - color = "rgb(76, 110, 219)"; - break; - case "BEV": - color = "rgb(35, 171, 216)"; - break; - case "FCEV": - color = "rgb(29, 223, 163)"; - break; - } - - return color; - }) - .append("title") //Make tooltip - .text(function(d) { - return d.key; - }); + //Create areas for TYPES + svg.append("g") + .attr("id", "types") + .selectAll("path") + .data(typeSeries) + .enter() + .append("path") + .attr("class", "area") + .attr("d", area) + .attr("fill", function(d) { + + //Which type is this? + var thisType = d.key; + + //New color var + var color; + + switch (thisType) { + case "HEV": + color = "rgb(110, 64, 170)"; + break; + case "PHEV": + color = "rgb(76, 110, 219)"; + break; + case "BEV": + color = "rgb(35, 171, 216)"; + break; + case "FCEV": + color = "rgb(29, 223, 163)"; + break; + } + + return color; + }) + .append("title") //Make tooltip + .text(function(d) { + return d.key; + }); //Click to fade out types d3.select("g#types") diff --git a/chapter_16/05_click_transition.html b/chapter_16/05_click_transition.html index 1800e78..d64fe1a 100644 --- a/chapter_16/05_click_transition.html +++ b/chapter_16/05_click_transition.html @@ -286,104 +286,104 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar return d.key; }); - //Create areas for TYPES - svg.append("g") - .attr("id", "types") - .selectAll("path") - .data(typeSeries, key) - .enter() - .append("path") - .attr("class", "area") - .attr("d", area) - .attr("fill", function(d) { - - //Which type is this? - var thisType = d.key; - - //New color var - var color; - - switch (thisType) { - case "HEV": - color = "rgb(110, 64, 170)"; - break; - case "PHEV": - color = "rgb(76, 110, 219)"; - break; - case "BEV": - color = "rgb(35, 171, 216)"; - break; - case "FCEV": - color = "rgb(29, 223, 163)"; - break; - } - - return color; - }) - .on("click", function(d) { - - //Which type was clicked? - var thisType = d.key; - - //Generate a new data set with all-zero values, - //except for this type's data - var thisTypeDataset = []; - - for (var i = 0; i < typeDataset.length; i++) { - thisTypeDataset[i] = { - date: typeDataset[i].date, - HEV: 0, - PHEV: 0, - BEV: 0, - FCEV: 0, - [thisType]: typeDataset[i][thisType] //Overwrites the appropriate zero value above - } + //Create areas for TYPES + svg.append("g") + .attr("id", "types") + .selectAll("path") + .data(typeSeries, key) + .enter() + .append("path") + .attr("class", "area") + .attr("d", area) + .attr("fill", function(d) { + + //Which type is this? + var thisType = d.key; + + //New color var + var color; + + switch (thisType) { + case "HEV": + color = "rgb(110, 64, 170)"; + break; + case "PHEV": + color = "rgb(76, 110, 219)"; + break; + case "BEV": + color = "rgb(35, 171, 216)"; + break; + case "FCEV": + color = "rgb(29, 223, 163)"; + break; + } + + return color; + }) + .on("click", function(d) { + + //Which type was clicked? + var thisType = d.key; + + //Generate a new data set with all-zero values, + //except for this type's data + var thisTypeDataset = []; + + for (var i = 0; i < typeDataset.length; i++) { + thisTypeDataset[i] = { + date: typeDataset[i].date, + HEV: 0, + PHEV: 0, + BEV: 0, + FCEV: 0, + [thisType]: typeDataset[i][thisType] //Overwrites the appropriate zero value above } + } + + // console.log(thisTypeDataset); + + //Stack the data (even though there's now just one "layer") and log it out + var thisTypeSeries = typeStack(thisTypeDataset); + // console.log(thisTypeSeries); + + //Bind the new data set to paths, overwriting old bound data. + var paths = d3.selectAll("#types path") + .data(thisTypeSeries, key); + + //Transition areas into new positions (i.e., thisType's area + //will go to a zero baseline; all others will flatten out). + // + //Store this transition in a new variable for later reference. + var areaTransitions = paths.transition() + .duration(1000) + .attr("d", area); - // console.log(thisTypeDataset); - - //Stack the data (even though there's now just one "layer") and log it out - var thisTypeSeries = typeStack(thisTypeDataset); - // console.log(thisTypeSeries); + //Update scale + yScale.domain([ + 0, + d3.max(thisTypeDataset, function(d) { + var sum = 0; + + //Calculate the total (sum) of sales of this type, + //ignoring the others (for now) + sum += d[thisType]; + + return sum; + }) + ]); + + //Append this transition to the one already in progress + //(from above). Transition areas to newly updated scale. + areaTransitions.transition() + .delay(200) + .duration(1000) + .attr("d", area); - //Bind the new data set to paths, overwriting old bound data. - var paths = d3.selectAll("#types path") - .data(thisTypeSeries, key); - - //Transition areas into new positions (i.e., thisType's area - //will go to a zero baseline; all others will flatten out). - // - //Store this transition in a new variable for later reference. - var areaTransitions = paths.transition() - .duration(1000) - .attr("d", area); - - //Update scale - yScale.domain([ - 0, - d3.max(thisTypeDataset, function(d) { - var sum = 0; - - //Calculate the total (sum) of sales of this type, - //ignoring the others (for now) - sum += d[thisType]; - - return sum; - }) - ]); - - //Append this transition to the one already in progress - //(from above). Transition areas to newly updated scale. - areaTransitions.transition() - .delay(200) - .duration(1000) - .attr("d", area); - - }) - .append("title") //Make tooltip - .text(function(d) { - return d.key; - }); + }) + .append("title") //Make tooltip + .text(function(d) { + return d.key; + }); //Create axes svg.append("g") diff --git a/chapter_16/06_update_axis.html b/chapter_16/06_update_axis.html index e738d27..fee528f 100644 --- a/chapter_16/06_update_axis.html +++ b/chapter_16/06_update_axis.html @@ -286,113 +286,113 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar return d.key; }); - //Create areas for TYPES - svg.append("g") - .attr("id", "types") - .selectAll("path") - .data(typeSeries, key) - .enter() - .append("path") - .attr("class", "area") - .attr("d", area) - .attr("fill", function(d) { - - //Which type is this? - var thisType = d.key; - - //New color var - var color; - - switch (thisType) { - case "HEV": - color = "rgb(110, 64, 170)"; - break; - case "PHEV": - color = "rgb(76, 110, 219)"; - break; - case "BEV": - color = "rgb(35, 171, 216)"; - break; - case "FCEV": - color = "rgb(29, 223, 163)"; - break; - } - - return color; - }) - .on("click", function(d) { - - //Which type was clicked? - var thisType = d.key; - - //Generate a new data set with all-zero values, - //except for this type's data - var thisTypeDataset = []; - - for (var i = 0; i < typeDataset.length; i++) { - thisTypeDataset[i] = { - date: typeDataset[i].date, - HEV: 0, - PHEV: 0, - BEV: 0, - FCEV: 0, - [thisType]: typeDataset[i][thisType] //Overwrites the appropriate zero value above - } + //Create areas for TYPES + svg.append("g") + .attr("id", "types") + .selectAll("path") + .data(typeSeries, key) + .enter() + .append("path") + .attr("class", "area") + .attr("d", area) + .attr("fill", function(d) { + + //Which type is this? + var thisType = d.key; + + //New color var + var color; + + switch (thisType) { + case "HEV": + color = "rgb(110, 64, 170)"; + break; + case "PHEV": + color = "rgb(76, 110, 219)"; + break; + case "BEV": + color = "rgb(35, 171, 216)"; + break; + case "FCEV": + color = "rgb(29, 223, 163)"; + break; + } + + return color; + }) + .on("click", function(d) { + + //Which type was clicked? + var thisType = d.key; + + //Generate a new data set with all-zero values, + //except for this type's data + var thisTypeDataset = []; + + for (var i = 0; i < typeDataset.length; i++) { + thisTypeDataset[i] = { + date: typeDataset[i].date, + HEV: 0, + PHEV: 0, + BEV: 0, + FCEV: 0, + [thisType]: typeDataset[i][thisType] //Overwrites the appropriate zero value above } + } + + // console.log(thisTypeDataset); + + //Stack the data (even though there's now just one "layer") and log it out + var thisTypeSeries = typeStack(thisTypeDataset); + // console.log(thisTypeSeries); + + //Bind the new data set to paths, overwriting old bound data. + var paths = d3.selectAll("#types path") + .data(thisTypeSeries, key); + + //Transition areas into new positions (i.e., thisType's area + //will go to a zero baseline; all others will flatten out). + // + //Store this transition in a new variable for later reference. + var areaTransitions = paths.transition() + .duration(1000) + .attr("d", area); - // console.log(thisTypeDataset); - - //Stack the data (even though there's now just one "layer") and log it out - var thisTypeSeries = typeStack(thisTypeDataset); - // console.log(thisTypeSeries); - - //Bind the new data set to paths, overwriting old bound data. - var paths = d3.selectAll("#types path") - .data(thisTypeSeries, key); - - //Transition areas into new positions (i.e., thisType's area - //will go to a zero baseline; all others will flatten out). - // - //Store this transition in a new variable for later reference. - var areaTransitions = paths.transition() - .duration(1000) - .attr("d", area); - - //Update scale - yScale.domain([ - 0, - d3.max(thisTypeDataset, function(d) { - var sum = 0; - - //Calculate the total (sum) of sales of this type, - //ignoring the others (for now) - sum += d[thisType]; - - return sum; - }) - ]); - - //Append this transition to the one already in progress - //(from above). Transition areas to newly updated scale. - areaTransitions.transition() - .delay(200) - .on("start", function() { - - //Transition axis to new scale concurrently - d3.select("g.axis.y") - .transition() - .duration(1000) - .call(yAxis); - + //Update scale + yScale.domain([ + 0, + d3.max(thisTypeDataset, function(d) { + var sum = 0; + + //Calculate the total (sum) of sales of this type, + //ignoring the others (for now) + sum += d[thisType]; + + return sum; }) - .duration(1000) - .attr("d", area); - - }) - .append("title") //Make tooltip - .text(function(d) { - return d.key; - }); + ]); + + //Append this transition to the one already in progress + //(from above). Transition areas to newly updated scale. + areaTransitions.transition() + .delay(200) + .on("start", function() { + + //Transition axis to new scale concurrently + d3.select("g.axis.y") + .transition() + .duration(1000) + .call(yAxis); + + }) + .duration(1000) + .attr("d", area); + + }) + .append("title") //Make tooltip + .text(function(d) { + return d.key; + }); //Create axes svg.append("g") diff --git a/chapter_16/07_hide_reveal_vehicles.html b/chapter_16/07_hide_reveal_vehicles.html new file mode 100644 index 0000000..734c817 --- /dev/null +++ b/chapter_16/07_hide_reveal_vehicles.html @@ -0,0 +1,463 @@ + + + + + D3: Hide and reveal vehicles + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file diff --git a/chapter_16/08_zoom_to_vehicle.html b/chapter_16/08_zoom_to_vehicle.html new file mode 100644 index 0000000..aee92d8 --- /dev/null +++ b/chapter_16/08_zoom_to_vehicle.html @@ -0,0 +1,463 @@ + + + + + D3: Zoom to vehicle + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file From 9d560abc7445e36f62ae9e423b89dc18fd4d4271 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 20 Apr 2017 13:15:23 -0700 Subject: [PATCH 69/85] Removed old scratch files --- chapter_16/z23_bar_page_side_by_side.html | 442 ------------------ chapter_16/z5_framing.html | 200 -------- chapter_16/zvehicle_sales_data_TRANSPOSED.csv | 93 ---- 3 files changed, 735 deletions(-) delete mode 100644 chapter_16/z23_bar_page_side_by_side.html delete mode 100755 chapter_16/z5_framing.html delete mode 100644 chapter_16/zvehicle_sales_data_TRANSPOSED.csv diff --git a/chapter_16/z23_bar_page_side_by_side.html b/chapter_16/z23_bar_page_side_by_side.html deleted file mode 100644 index 9037fb1..0000000 --- a/chapter_16/z23_bar_page_side_by_side.html +++ /dev/null @@ -1,442 +0,0 @@ - - - - - D3: Dynamically sized charts happily coexist side-by-side - - - - - - - - -
- -

Five New Data Insights You Have to See to Believe

- -

You won’t believe your eyes when you realize what these charts are telling you. The numbers don’t lie, and sometimes facing the facts can cause a shock. No one could have predicted this, and no one knew it was true until we published these innovative visualizations, thereby proving definitively that a picture is worth a thousand words. (Edit the source to add more cliches here.)

- -
-

Total sales by employee in July 2015

-
- -
-

Total bonuses by employee in July 2015

-
- -
- -
- - - -
- - - - - - \ No newline at end of file diff --git a/chapter_16/z5_framing.html b/chapter_16/z5_framing.html deleted file mode 100755 index b09840e..0000000 --- a/chapter_16/z5_framing.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - Bar Chart, Framed - - - - - -
- -

Not All Countries are Equally Satisfied

- -

The OECD’s Better Life Index assigns each country a “Life Satisfaction” score. Source: OECD, 2014

- -
- - - - - \ No newline at end of file diff --git a/chapter_16/zvehicle_sales_data_TRANSPOSED.csv b/chapter_16/zvehicle_sales_data_TRANSPOSED.csv deleted file mode 100644 index 7e81977..0000000 --- a/chapter_16/zvehicle_sales_data_TRANSPOSED.csv +++ /dev/null @@ -1,93 +0,0 @@ -Make,Model,Type,2005-01,2005-02,2005-03,2005-04,2005-05,2005-06,2005-07,2005-08,2005-09,2005-10,2005-11,2005-12,2006-01,2006-02,2006-03,2006-04,2006-05,2006-06,2006-07,2006-08,2006-09,2006-10,2006-11,2006-12,2007-01,2007-02,2007-03,2007-04,2007-05,2007-06,2007-07,2007-08,2007-09,2007-10,2007-11,2007-12,2008-01,2008-02,2008-03,2008-04,2008-05,2008-06,2008-07,2008-08,2008-09,2008-10,2008-11,2008-12,2009-01,2009-02,2009-03,2009-04,2009-05,2009-06,2009-07,2009-08,2009-09,2009-10,2009-11,2009-12,2010-01,2010-02,2010-03,2010-04,2010-05,2010-06,2010-07,2010-08,2010-09,2010-10,2010-11,2010-12,2011-01,2011-02,2011-03,2011-04,2011-05,2011-06,2011-07,2011-08,2011-09,2011-10,2011-11,2011-12,2012-01,2012-02,2012-03,2012-04,2012-05,2012-06,2012-07,2012-08,2012-09,2012-10,2012-11,2012-12,2013-01,2013-02,2013-03,2013-04,2013-05,2013-06,2013-07,2013-08,2013-09,2013-10,2013-11,2013-12,2014-01,2014-02,2014-03,2014-04,2014-05,2014-06,2014-07,2014-08,2014-09,2014-10,2014-11,2014-12,2015-01,2015-02,2015-03,2015-04,2015-05,2015-06,2015-07,2015-08,2015-09,2015-10,2015-11,2015-12,2016-01,2016-02,2016-03,2016-04,2016-05,2016-06,2016-07,2016-08,2016-09,2016-10,2016-11,2016-12,2017-01,2017-02 -Honda,Insight,HEV,7,22,56,90,52,69,68,80,83,37,60,42,59,72,79,110,92,77,91,109,19,9,2,3,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,569,2096,2780,2079,2295,4226,1746,1739,1403,1639,1307,2014,1652,1880,1913,1491,1858,2030,1679,1965,1536,1637,1554,1722,2782,2644,1435,1021,987,961,512,492,749,690,492,773,1032,738,512,494,419,341,246,251,238,310,319,388,454,391,426,384,420,438,299,463,402,418,317,339,410,441,493,333,291,290,240,222,278,311,223,211,209,183,139,126,113,85,64,53,30,22,19,0,2,9,9,9,5,9,1,0,3,9,1,0 -Toyota,Prius,HEV,5566,7078,10236,11345,9461,9622,9691,9850,8193,9939,7889,9027,7654,6547,7922,8234,8103,9696,11114,11177,10492,8733,8008,9291,8299,12227,19156,13056,24009,17756,16062,14055,12494,13158,16737,14212,11379,10895,20635,21757,15011,11765,14785,13463,10873,11804,8660,7859,8121,7232,8924,8385,10091,12998,19173,18886,10984,13496,9617,11775,8484,7968,11786,12555,14248,10998,14102,11799,11394,11731,10224,15639,10635,13539,18605,12477,6924,4340,7907,9491,9325,11008,15208,17004,11555,20589,27800,23514,20391,18455,15955,20064,17280,14885,14739,18679,14898,17119,21354,19290,22844,20495,22477,25567,14738,13528,15029,14801,11402,11820,17130,16270,24101,17078,19304,22619,13924,13032,13506,13922,11843,11621,15565,14807,18836,14587,17340,17413,15894,15112,12531,15054,9301,10544,12068,11921,12513,11016,12690,12982,12471,8132,9714,10803,6463,7682 -Honda,Civic,HEV,1169,1353,2896,3466,1895,1852,2329,4146,1916,231,2083,2528,3166,1781,2232,3087,2890,2601,2673,3411,2508,2288,2208,2408,1783,1924,2813,2855,4520,3246,2493,2102,2092,2286,3238,3223,1745,1808,3769,4324,4676,2710,3440,3105,2020,1621,1043,1036,1076,1362,2869,3361,2077,1583,969,717,152,239,243,471,253,346,579,621,717,595,617,761,667,662,612,906,653,532,441,121,268,418,311,106,305,480,503,565,449,741,906,766,708,548,471,579,493,453,530,512,429,433,572,569,570,568,578,697,402,1158,1031,712,439,443,338,450,415,410,409,503,360,395,432,476,320,358,351,386,458,391,463,590,613,455,239,263,161,143,166,92,83,62,60,50,38,14,15,12,16,8 -Ford,Escape,HEV,908,1092,1569,1705,1234,1126,1168,1363,1808,1313,1121,1553,898,1341,1590,3420,2862,1884,2060,1789,1651,1602,1484,1968,1238,1696,2523,2275,3214,2526,1578,1833,1652,2084,2224,2265,1474,1743,2008,1907,2378,1912,1265,1338,990,1997,1361,1149,880,1294,1351,1134,1827,1405,2543,2102,878,949,960,1157,715,782,1282,1119,1383,1360,1220,790,842,809,814,972,520,795,1195,1070,1118,826,652,563,566,573,1131,1080,345,434,162,0,206,17,50,34,81,9,21,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Honda,Accord,HEV,805,855,1862,2023,1314,1080,1376,2336,2352,1266,837,720,351,783,581,614,520,396,504,499,389,287,311,363,248,312,385,318,439,342,260,275,229,243,204,150,48,42,53,25,16,7,3,2,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,23,530,426,525,910,1346,1442,1530,1135,1362,1175,1095,1130,1094,1233,805,832,948,1118,1463,1241,1481,1369,854,442,289,223,71,68,51,29,15,31,565,890,1160,1296,1879,3124,1711,1867 -Toyota,Highlander,HEV,,,,,35,2869,2564,2925,2715,2330,2353,2198,2263,2631,2987,3768,3755,2705,2784,2581,2347,1643,1667,2354,1810,1892,2501,2394,3312,2403,1205,378,193,596,2577,2791,2143,1938,2239,2578,2644,1511,1371,1227,921,1022,907,890,984,956,1037,933,1351,1098,1171,836,269,700,722,1029,526,339,594,692,683,611,575,486,523,756,722,949,689,707,797,380,149,74,185,226,218,239,322,563,362,474,607,552,560,496,469,449,413,466,485,588,452,441,477,495,545,550,410,440,325,331,332,272,145,105,333,418,355,280,214,288,303,327,425,428,268,256,295,305,323,311,304,377,367,375,318,516,375,396,492,442,473,528,524,506,383,356,483,1018,571,1339 -Lexus,RX 450h,HEV,,,13,2345,2931,2605,2262,2607,2113,1904,1722,2172,1477,1803,2470,2247,2006,1190,1220,1514,1687,1239,1327,1981,1245,1249,1471,1384,1746,1562,1385,1172,979,1392,1674,2032,1211,1148,1570,1624,2155,1330,1439,1277,744,615,624,1463,1556,1502,1165,655,393,527,1369,1754,1168,1567,1210,1598,1016,890,1251,1232,1358,1304,1356,1370,1112,1402,1293,1535,912,999,1438,1167,610,413,671,841,650,861,928,1233,753,826,992,801,1011,1193,1171,1170,944,997,971,1394,744,756,925,688,885,900,962,1116,815,1258,1105,1153,637,621,852,387,837,872,914,1090,695,728,788,930,521,494,641,492,551,486,530,599,443,514,958,1493,790,752,886,899,719,684,684,574,387,535,666,985,443,507 -Toyota,Camry,HEV,,,,,,,,,,,,,,,,86,3032,4268,5023,4977,4044,2806,3100,4005,2801,3332,5144,4410,6853,5530,4329,4284,4196,3511,5118,4969,3750,4121,6930,6678,5999,3054,2645,3456,2785,2792,2174,1888,1141,2080,2554,2198,2941,2093,2509,2114,872,1407,1465,1513,867,1011,1549,1655,1455,1097,1276,1165,1104,1194,983,1231,860,993,1437,1110,592,449,393,318,229,333,730,1797,2116,3750,5404,4406,4403,3471,3197,3840,3704,2986,3936,4443,3826,4147,4461,3257,4265,3878,4193,4729,3069,2903,2994,2726,1978,2517,4287,3916,5199,3874,4609,4320,1986,2161,2220,2448,2143,2110,2739,2650,3174,2755,2756,3314,2629,2545,1964,1861,1256,1599,1746,1975,2055,1649,2214,2155,1902,1802,1693,2181,1238,1333 -Lexus,GS 450h,HEV,,,,,,,,,,,,,,,,141,294,231,157,192,164,177,176,252,167,160,181,174,181,131,142,130,72,71,100,136,64,77,65,82,98,73,40,35,29,22,42,51,41,22,42,33,43,27,45,48,38,39,37,54,41,22,31,25,38,22,16,15,18,29,18,30,19,33,24,29,18,24,26,17,18,19,22,33,25,20,12,10,42,75,60,94,89,68,60,52,34,38,56,34,39,55,63,69,31,34,25,44,30,23,25,35,9,15,8,13,3,2,9,11,8,10,9,12,8,7,11,4,7,7,5,3,5,5,8,16,7,3,12,3,4,0,1,6,6,5 -Lexus,HS 250h,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,543,1242,1527,1407,1980,1247,712,1494,1076,1360,603,165,594,711,792,788,1121,286,183,230,279,220,159,306,284,231,205,207,274,152,150,261,28,21,10,5,7,8,3,3,2,0,1,1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Nissan,Altima,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,206,462,483,821,804,1131,643,756,927,1191,964,473,529,832,801,1607,1333,715,442,470,554,353,710,644,463,834,222,345,666,1030,3164,345,299,503,842,1059,619,394,330,1167,479,378,284,511,443,434,612,365,366,545,334,499,250,204,318,217,49,55,34,27,22,18,10,9,3,7,0,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Lexus,LS 600hL,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,267,196,175,170,129,105,112,113,122,112,73,83,71,47,55,37,50,33,22,25,19,27,31,28,10,12,21,15,15,9,15,9,7,8,4,14,15,9,9,13,17,8,7,9,10,1,4,6,9,8,9,5,9,8,6,5,8,6,6,1,0,1,5,2,6,14,22,12,15,11,10,6,5,3,6,5,6,11,11,7,9,5,5,6,4,0,2,1,4,5,7,7,5,7,1,5,3,3,1,0,3,3,2,4,5,2,1,2,11,6,0,2,2,0,0 -Saturn,Vue,HEV,,,,,,,,,,,,,,,,,,,,,,,,,793,793,793,793,797,,,,,,,,135,135,135,135,340,277,362,417,443,354,328,338,153,188,362,338,227,239,269,414,90,56,134,186,14,4,8,4,3,14,0,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Chevrolet,Tahoe,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,233,234,234,234,589,547,351,798,1101,795,767,1729,599,632,609,523,641,547,538,562,615,792,489,645,278,315,368,399,565,368,262,252,215,245,213,377,217,191,278,276,229,129,115,76,31,88,79,168,76,151,227,144,161,124,132,135,110,146,171,224,97,91,109,116,154,120,58,83,45,55,51,57,21,12,26,14,14,21,6,7,2,5,6,3,3,8,1,4,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Chevrolet,Malibu,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,112,112,112,112,282,295,349,388,382,325,195,454,145,197,547,547,706,489,476,441,156,114,212,132,67,68,80,67,41,36,14,12,2,6,7,5,0,0,0,0,2,22,0,0,0,0,0,0,1,350,1416,1557,1642,2002,1938,2414,1656,1266,1041,1381,981,1254,1359,1551,1695,1651,1338,1582,858,819,425,266,232,202,191,130,94,62,30,21,10,17,14,15,6,8,8,4,2,27,1,0,1,1,0,1,0,0,2,1,246,371,416,522,618,600,769,790,339,534 -Saturn,Aura,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,14,14,14,15,36,30,29,26,31,22,45,34,19,23,26,31,35,56,24,65,30,30,29,159,25,2,4,0,2,5,4,3,1,4,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Dodge,Durango,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,46,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Chevrolet,Silverado,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,47,68,95,130,123,180,226,120,167,156,279,97,106,180,161,337,120,135,379,232,391,97,158,213,67,120,119,111,90,37,23,82,53,45,205,25,54,94,42,62,38,48,96,29,72,188,192,19,21,18,27,20,13,10,13,6,9,7,6,1,3,1,3,4,9,1,1,1,1,4,1,2,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 -Ford,Fusion,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,451,1165,2079,2244,2810,2593,1260,1333,1401,1686,1152,1317,1784,1607,2562,2103,1676,3104,1756,1816,1586,1769,969,1379,1466,1285,1256,969,456,216,552,857,993,888,611,1110,1009,778,683,797,1109,1071,898,956,1834,3244,3043,3806,3417,3625,3335,3057,2914,3694,2265,2577,2769,2768,2607,3096,3903,3537,4641,3016,2851,2943,1972,2164,2323,2372,1782,2416,2534,1820,2440,1691,2157,2441,2002,2050,1388,1960,1373,1764,2057,2035,1716,2542,3519,3002,3776,4915,3372,3577,4856,4939 -Mercedes-Benz,S400,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,77,77,98,108,101,63,69,84,83,114,39,42,26,24,25,32,49,26,25,15,22,9,19,37,11,28,10,8,7,8,5,11,9,10,4,10,12,9,8,7,8,5,8,2,0,0,3,2,1,2,1,0,0,0,0,0,1,0,1,4,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Mercedes-Benz,ML450,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,70,69,67,37,181,212,24,79,24,2,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,3,2,2,2,0,0,0,3,6,0,0,0,0,2,0,0,0,0,0,1,2,0,0,7,0,0,0,0,0,0,10,0,0,2,2,0,5,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Mercedes-Benz,E320,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Mazda,Tribute,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,43,42,59,58,61,55,68,55,53,67,46,48,36,37,34,37,35,64,48,51,32,38,36,36,24,21,29,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -BMW,X6,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,22,21,21,21,12,128,3,3,2,0,9,6,5,9,5,2,3,6,5,0,4,2,-1,3,0,0,2,-1,1,1,1,0,0,-1,2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -BMW,Activehybrid3&5&7,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,11,9,26,9,7,8,25,32,35,38,32,38,27,20,15,16,9,25,51,31,60,54,29,26,9,21,25,40,321,214,206,77,133,133,223,138,134,129,95,59,85,106,144,34,39,43,25,30,37,16,16,32,9,10,17,7,1,11,3,7,8,6,3,2,0,4,11,2,0,1,2,8,0,3,0,7,23,18,0,0,0 -Honda,CR-z,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,694,1236,1419,1024,876,894,1091,1685,1819,1557,966,878,745,537,289,305,564,363,466,536,334,296,409,330,392,335,244,244,243,358,381,451,405,427,393,384,483,264,325,295,384,267,318,354,369,389,302,356,342,248,205,188,224,196,175,255,216,246,204,270,333,310,316,236,316,192,128,163,253,234,235,272,222,165,168,146,160,89,118 -Lincoln,MKZ,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,366,392,424,370,395,615,503,561,483,480,491,455,477,475,434,253,419,626,397,480,451,594,998,781,465,282,321,100,177,446,884,715,768,646,791,619,717,852,754,726,919,1411,1047,1128,787,638,758,645,662,569,743,468,480,717,810,1005,700,725,713,596,646,676,867,491,585,608,613,805,766,681,541,460,450,552,667,467,570 -Porsche,Cayenne,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,206,211,142,114,107,114,177,130,128,112,107,140,89,112,137,124,104,150,42,60,69,84,106,108,84,60,32,46,46,48,62,39,43,67,59,58,55,45,64,96,84,75,72,159,14,13,18,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Lexus,CT 200h,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2199,875,454,240,1553,2087,1444,1511,1759,2259,1025,1640,2223,1620,1549,1387,1499,1472,1195,1199,1264,1598,1001,1182,1062,1171,1623,1513,1306,1784,798,842,1002,1787,1290,1230,1480,1054,1762,1521,1979,2191,1078,1158,1322,1608,1005,978,1416,1170,1436,1118,1374,1504,1131,1077,984,1464,622,762,972,577,797,785,849,819,638,564,550,968,393,458 -Volkswagen,Touareg,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,65,60,44,52,40,23,14,10,14,18,21,29,36,18,19,12,18,25,27,17,5,11,44,18,21,43,12,7,6,12,3,7,3,1,1,2,3,0,4,3,3,6,2,4,1,1,1,2,2,1,3,0,6,2,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 -Infinity,Q70 (M35h),HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,42,36,33,35,54,45,33,46,54,35,58,47,23,78,73,59,60,45,66,71,76,37,46,58,35,42,47,33,44,33,34,33,33,44,14,19,11,12,11,8,5,6,13,17,20,19,14,22,15,14,12,11,13,12,14,14,16,10,10,12,11,10,10,10,9,8,9,7,12,5,4 -Hyundai,Sonata,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1422,4177,4136,2000,2001,1723,1907,1304,1568,2095,1847,1869,1884,1888,1766,1560,1510,1589,1874,1192,1441,1623,1447,1817,2129,2200,2303,2102,1318,1866,2121,1340,1907,2430,2055,2094,1523,2800,1910,2134,1181,781,897,672,1605,1793,2481,2943,2334,1837,1647,1185,1342,931,1138,964,1588,1884,1788,2513,1242,1301,1146,1815,1479,1867,1374,1113,1471 -Buick,LaCrosse,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,297,522,982,781,1248,1117,1165,1202,1245,867,1024,840,978,724,819,576,706,717,662,668,619,530,803,423,552,430,447,445,506,536,716,772,610,462,545,587,704,772,698,326,514,497,531,498,341,322,275,200,199,194,145,118,87,83,115,42,60,55,60,35,53,31,26,18,12 -Buick,Regal,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,86,63,137,135,130,174,219,233,331,463,287,211,181,184,375,387,389,291,227,183,214,185,178,187,93,78,88,95,41,64,75,34,47,32,40,46,22,12,20,21,28,23,17,8,16,13,11,9,8,3,7,7,14,7,4,2,0,0,0,0,1,3,0 -Porsche,Panamera S,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,26,26,39,34,43,26,73,25,35,48,86,48,67,46,46,5,11,5,7,4,29,0,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Kia,Optima,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,705,925,1201,837,810,933,848,907,902,745,681,751,909,1215,1001,1000,1206,1100,1241,1601,1272,1151,1233,990,777,960,1879,1060,735,1006,1155,1318,1003,1483,1101,1299,844,856,805,892,1046,897,873,1167,1136,1262,844,870,469,386,436,483,570,483,768,654,591,482,423,397,279,257 -Acura,ILX,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,34,115,110,136,140,144,174,119,84,154,145,152,195,163,110,125,108,137,44,44,27,42,46,49,63,44,35,24,15,15,10,9,3,5,4,2,4,1,0,0,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,,0, -Ford,C-Max,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,969,3038,3589,3339,2387,2849,3275,3197,3261,2889,2267,2411,1424,1438,1457,1201,947,1301,1685,1586,2051,1952,2163,2451,1109,1318,1296,1303,765,878,1054,1237,1892,1814,1225,1501,1247,912,815,837,637,880,1092,1621,1327,1486,1112,879,739,398,811,895,473,676 -Lexus,ES Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,817,1400,1520,1424,1866,1324,1154,1561,1237,1434,1239,1324,1600,1223,1367,1393,1706,866,945,1384,1242,1408,1102,1358,1628,1128,1182,1194,1400,746,758,1076,789,911,711,891,1281,907,895,833,1443,622,633,894,700,735,646,705,692,497,353,434,734,242,330 -Audi,Q5 Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,33,90,122,90,76,84,86,105,83,47,73,73,56,38,43,36,24,35,21,25,19,22,31,19,24,16,11,8,10,9,7,17,5,8,5,3,5,7,13,3,0,5,2,2,2,1,2,1,0,0,0,0,0 -Toyota,Avalon,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,747,1040,1361,1616,1423,1514,1394,1139,1467,1104,1398,1532,1480,970,613,1600,1522,1957,1437,1767,2049,1437,1330,1212,1154,912,864,902,906,1114,973,1175,1322,1064,993,798,933,583,590,776,715,660,619,707,775,688,673,639,1026,448,464 -Volkswagen,Jetta,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,162,232,272,451,353,473,438,417,712,887,666,394,360,224,232,276,149,209,206,156,151,114,97,68,57,50,36,45,41,55,66,91,98,77,64,52,65,46,39,47,46,47,44,87,128,76,48,45,56,13,12 -Mercedes-Benz,E400H,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,22,22,25,17,29,23,26,29,27,22,20,20,23,15,9,39,16,13,5,7,12,5,5,9,30,3,13,0,2,0,2,2,0,1,0,0,1,0,1,0,1,4,2,1,2,0,2,0,1,0 -Infiniti,Q50,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,47,51,118,91,59,328,380,263,294,242,246,266,274,296,422,386,297,365,390,299,342,347,381,384,356,381,189,281,175,202,335,147,95,94,112,150,174,148,134,232,128,138 -Chevrolet,Impala Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,16,35,34,38,49,34,58,63,43,63,35,32,23,93,19,19,29,49,53,24,23,27,5,11,1,12,12,4,4,3,2,10,0,0,0,0,0,0,0,0 -Infiniti,QX60,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,302,374,238,135,167,114,137,108,112,130,109,114,146,168,129,179,195,170,188,180,226,240,231,220,149,249,119,137,195,66,85,88,74,65,63,59,64,99,44,53 -Nissan,Pathfinder Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,334,265,191,237,183,238,191,221,237,160,166,187,204,184,212,258,167,223,215,234,212,186,168,102,84,65,72,87,56,60,57,55,58,80,64,68,94,73,90 -Subaru,XV,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,470,546,725,711,1003,788,746,747,571,617,575,427,512,549,587,552,557,493,559,455,370,211,319,425,261,278,329,303,303,214,193,117,79,44,27,25,13,6 -Acura,RLX,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,31,36,37,29,14,21,18,15,24,27,28,34,26,14,13,16,0,12,19,19,18,0,11,19,24,13,33,31,11,27 -Lexus,NX Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,354,163,164,225,210,250,203,234,206,170,188,196,364,245,236,251,222,229,183,228,224,233,188,241,362,179,184 -Toyota,RAV4,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,64,1430,1973,2462,3073,3807,4185,3751,4692,4919,4127,3551,3757,4773,2898,3080 -Acura,NSX,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,21,22,38,67,51,68,50,46 -Kia,Niro Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,42,2143 -Hyundai,Ioniq Hybrid,HEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,1 -Chevrolet,Volt,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,326,321,281,608,493,481,561,125,302,723,1108,1139,1529,603,1023,2289,1462,1680,1760,1849,2831,2851,2961,1519,2633,1140,1626,1478,1306,1607,2698,1788,3351,1766,2022,1920,2392,918,1210,1478,1548,1684,1777,2020,2511,1394,1439,1336,1490,542,693,639,905,1618,1225,1313,1380,949,2035,1980,2114,996,1126,1865,1983,1901,1937,2406,2081,2031,2191,2531,3691,1611,1820 -Prius,PHEV,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,911,1654,1086,695,688,1047,1652,1889,1766,1361,874,693,786,599,678,584,817,1791,1152,2095,1100,919,803,1041,1452,1741,2692,1571,1371,818,353,479,451,492,401,397,473,428,727,464,584,344,216,91,44,22,10,6,7,4,4,11,4,2,4,0,781,1641,1366,1362 -Ford,C-Max Energi,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,144,1259,971,338,334,494,411,450,455,433,621,758,1092,941,827,471,552,610,525,782,988,831,1050,677,644,644,659,395,498,715,553,715,667,693,723,719,695,639,579,350,490,610,607,538,630,755,707,689,571,721,1289,473,639 -Honda,Accord,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,17,26,55,58,42,54,44,51,71,68,38,27,24,18,37,46,28,41,46,42,34,43,63,28,12,5,5,5,4,1,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Ford,Fusion Energi,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,119,295,364,416,390,407,600,750,1087,870,791,533,779,899,743,1342,1939,1226,1222,640,686,752,789,426,603,837,711,986,727,852,949,808,849,944,1058,581,932,1238,1331,1453,1700,1341,1422,1652,1372,1817,1099,606,837 -Porsche,Panamera S E-Hybrid,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,47,141,57,56,63,53,111,63,68,82,97,57,31,61,40,44,30,21,34,23,36,41,28,33,16,27,33,23,25,26,22,21,59,28,38,88,3,2,1 -Cadillac,ELR,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,6,41,58,81,61,52,97,188,196,111,152,155,118,92,127,92,104,116,62,66,45,36,82,67,135,67,91,104,95,45,94,15,6,6,3,5,3,3,0 -BMW,i8,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,58,204,126,158,85,113,143,138,117,137,217,210,182,149,118,656,32,54,89,130,146,169,166,145,158,199,173,133,50,58 -Porsche,Cayenne S E-hybrid,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,67,83,106,72,88,111,89,77,83,70,126,121,137,146,172,244,237,191,176,148,197,131,138,179,152,177,121 -Mercedes-Benz,S550 Plug,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,17,25,21,35,19,36,12,29,27,27,32,30,41,174,52,71,55,51 -Volvo,XC90 Plug In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,0,1,7,74,226,176,178,150,110,166,178,176,148,142,161,204,96,83 -BMW,X5,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,285,607,181,345,313,655,500,583,649,876,482,406,436,569,262,275 -Hyundai,Sonata Plug In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,15,0,175,200,275,250,250,200,350,250,275,250,275,250,150,250 -Audi,A3 Plug In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,327,248,332,321,361,353,349,346,312,348,394,589,387,400 -BMW,3-series Plug-In,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,29,25,67,26,81,51,54,92,215,240,129,144 -Mercedes-Benz,GLE 550e,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,30,24,26,19,30,83,52,59 -BMW,7-series Plug-in,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,23,18,35 -Mercedes-Benz,C350We,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,171,210,51 -Kia,Optima Plug-in,PHEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,40,61 -Nissan,LEAF,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,87,67,298,573,1142,1708,931,1362,1031,849,672,954,676,478,579,370,510,535,395,685,984,1579,1539,1489,650,653,2236,1937,2138,2225,1864,2420,1953,2002,2003,2529,1252,1425,2507,2088,3117,2347,3019,3186,2881,2589,2687,3102,1070,1198,1817,1553,2104,2074,1174,1393,1247,1238,1054,1347,755,930,1246,787,979,1096,1063,1066,1316,1412,1457,1899,772,1037 -Smart,ED,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,16,16,0,0,8,0,1,1,0,17,101,182,0,2,0,0,0,127,6,1,0,0,3,0,1,1,0,0,60,53,58,182,137,111,153,167,97,122,186,203,206,278,298,208,182,150,313,351,147,76,103,124,102,94,109,106,94,75,178,179,48,54,70,66,75,53,62,55,44,43,47,40,15,22 -Mitsubishi,I EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,76,36,44,56,79,85,33,33,37,36,30,42,77,257,337,31,127,91,39,46,30,20,28,12,11,1,3,24,12,35,22,17,20,15,17,18,12,3,2,10,16,18,23,12,6,3,9,4,9,2,5,1,6,2,4,20,25,17,4,5,3,0,1 -BMW,Active E,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,112,115,326,30,11,79,0,0,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Ford,Focus,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,89,38,34,59,118,172,167,81,158,180,147,157,177,150,175,110,115,130,158,100,129,177,116,177,197,198,264,176,186,191,53,85,145,140,124,165,152,135,176,145,126,93,96,66,81,110,81,54,54,58,75,82,73,66,101,56,228 -Honda,Fit EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,9,16,16,26,19,8,15,23,22,15,208,63,66,35,40,23,51,30,33,37,50,33,38,42,55,29,23,5,32,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Tesla,Model S,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,150,450,800,900,1350,1450,1950,2100,2000,1800,1550,1700,1100,1300,1400,1700,1300,1400,1300,1400,1400,1400,1400,1200,1300,1300,1450,1900,1300,1400,2000,1900,2300,2800,1800,1600,2400,2100,3100,3500,1300,1900,3000,1700,1500,2800,2400,3200,4100,1200,1800,5300,1200,1700 -Toyota,RAV4 EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,47,32,52,25,52,133,70,84,44,109,231,167,0,62,28,63,101,73,69,149,91,68,228,125,97,83,37,7,2,4,4,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -Chevrolet,Spark,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,27,103,102,78,87,87,76,93,71,108,97,182,85,128,80,51,58,61,131,86,119,151,920,283,226,57,135,157,177,166,152,139,216,252,419,394,359,333,292,315,260,39,17,4,4 -Fiat,500E,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,50,50,50,60,50,35,40,166,152,167,166,119,166,137,140,100,115,119,117,164,450,471,411,353,370,347,231,174,270,217,195,373,372,388,278,274,311,370,319,287,353,305,283 -BMW,i3,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,336,358,363,1025,1022,1159,816,1013,670,1089,922,406,818,551,935,792,1710,986,723,1422,182,248,332,814,696,608,1479,1013,391,442,629,791,382,318 -Mercedes-Benz,B-Class,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,41,51,65,98,193,326,240,109,145,158,278,242,196,172,147,81,41,97,58,37,66,56,49,44,50,57,51,58,52,54,53,56 -Volkswagen,e-Golf,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,119,237,181,130,195,309,410,293,313,381,343,596,472,609,328,198,86,326,269,248,344,454,529,407,305,443,332,293 -Kia,Soul EV,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,109,140,110,69,48,63,73,108,109,59,93,105,109,83,96,81,60,79,139,120,134,179,153,217,190,179,197,117,152 -Tesla,Model X,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,10,15,177,400,500,1500,1500,2000,2000,1500,1900,2600,1000,1400,3300,1000,800 -Chevrolet,Bolt,BEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,579,1162,952 -Hyundai,Tucson,FCEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,10,10,6,1,10,12,6,3,3,1,2,2,0,1,5,1,0,0,2,3,4,4,4,8,8,2,4,0,0,1,2,5 -Toyota,Mirai,FCEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,0,2,38,23,15,26,30,41,41,40,40,52,371,69,103,105,116,83,110 -Honda,Clarity,FCEV,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,42,27 \ No newline at end of file From 34a0622ca3bbccdffe476f0e3cf09d52ab0271df Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sun, 23 Apr 2017 10:17:30 -0700 Subject: [PATCH 70/85] Example progress --- chapter_16/08_zoom_to_vehicle.html | 205 +++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/chapter_16/08_zoom_to_vehicle.html b/chapter_16/08_zoom_to_vehicle.html index aee92d8..89c2020 100644 --- a/chapter_16/08_zoom_to_vehicle.html +++ b/chapter_16/08_zoom_to_vehicle.html @@ -431,6 +431,211 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Get that color on the spectrum return d3.interpolateCool(normalized); + }) +//xxxx + .on("click", function(d) { + + //Which vehicle was clicked? + var thisType = d.key; + console.log("You clicked " + d.key); + + //Fade out all other vehicle areas + d3.selectAll("g#vehicles path") + .filter(function(d) { //Filter out 'this' one + if (d.key !== thisType) { + return true; + } + }) + .transition() + .duration(1000) + .attr("opacity", 0); + + //Zero-out baseline values, then transitioned into place. + + //Define area generator that will be used just this one time + var singleVehicleArea = d3.area() + .x(function(d) { return xScale(d.data.date); }) + .y0(function(d) { return yScale(0); }) //Note zero baseline + .y1(function(d) { return yScale(d.data[thisType].sales); }); + //Note y1 uses the raw 'sales' value for 'this' vehicle, + //not the stacked data values (e.g., d[0] or d[1]). + + d3.select(this) + .transition() + .delay(1000) + .duration(1000) + .attr("d", singleVehicleArea); + + + + // * A new y scale domain, based on the sales for this vehicle only, is calculated and set. + // * The clicked area and y axis are transitioned into place, to fit the new domain. + + + + + + // //Generate a new data set with all-zero values, + // //except for this vehicle's data + // var thisVehicleDataset = []; + // + // for (var i = 0; i < typeDataset.length; i++) { + // thisVehicleDataset[i] = { + // date: typeDataset[i].date, + // HEV: 0, + // PHEV: 0, + // BEV: 0, + // FCEV: 0, + // [thisType]: typeDataset[i][thisType] //Overwrites the appropriate zero value above + // } + // } + // + // // console.log(thisTypeDataset); + // + // //Stack the data (even though there's now just one "layer") and log it out + // var thisTypeSeries = typeStack(thisTypeDataset); + // // console.log(thisTypeSeries); + // + // //Bind the new data set to paths, overwriting old bound data. + // var paths = d3.selectAll("#types path") + // .data(thisTypeSeries, key) + // .classed("unclickable", "true"); + // + // //Transition areas into new positions (i.e., thisType's area + // //will go to a zero baseline; all others will flatten out). + // // + // //Store this transition in a new variable for later reference. + // var areaTransitions = paths.transition() + // .duration(1000) + // .attr("d", area); + // + // //Update scale + // yScale.domain([ + // 0, + // d3.max(thisTypeDataset, function(d) { + // var sum = 0; + // + // //Calculate the total (sum) of sales of this type, + // //ignoring the others (for now) + // sum += d[thisType]; + // + // return sum; + // }) + // ]); + // + // //Append this transition to the one already in progress + // //(from above). Transition areas to newly updated scale. + // areaTransitions.transition() + // .delay(200) + // .on("start", function() { + // + // //Transition axis to new scale concurrently + // d3.select("g.axis.y") + // .transition() + // .duration(1000) + // .call(yAxis); + // + // }) + // .duration(1000) + // .attr("d", area) + // .transition() + // .on("start", function() { + // //Make vehicles visible instantly, so + // //they are revealed when this fades out + // d3.selectAll("g#vehicles path") + // .attr("opacity", 1); + // }) + // .duration(1000) + // .attr("opacity", 0); + + + + // + // VEHICLES + // + + // //Get all possible keys (make + model), but toss out 'date' + // var keysAll = Object.keys(dataset[0]).slice(1); + // // console.log(keysAll); + // + // //Loop once for each key, and save out just the ones of thisType (e.g. BEVs) + // var keysOfThisType = []; + // for (var i = 0; i < keysAll.length; i++) { + // if (dataset[0][keysAll[i]].type == thisType) { + // keysOfThisType.push(keysAll[i]); + // } + // } + // // console.log(keysOfThisType); + // + // //Give the new keys to the stack function + // vehicleStack.keys(keysOfThisType) + // .value(function value(d, key) { + // return d[key].sales; + // }); + // + // //Stack the data and log it out + // var vehicleSeries = vehicleStack(dataset); + // // console.log(vehicleSeries); + // + // //Create areas for individual VEHICLES + // svg.select("g#vehicles") + // .selectAll("path") + // .data(vehicleSeries, key) + // .enter() + // .append("path") + // .attr("class", "area") + // .attr("opacity", 0) + // .attr("d", area) + // .attr("fill", function(d, i) { + // + // //Which vehicle is this? + // var thisKey = d.key; + // + // //What 'type' is this vehicle? + // var thisType = d[0].data[thisKey].type; + // // console.log(thisType); + // + // //Used to find a cool color below + // var spread = 0.2; + // var startingPoint; + // + // //Choose where in the color spectrum we start, based on type + // switch (thisType) { + // case "HEV": + // startingPoint = 0; + // break; + // case "PHEV": + // startingPoint = 0.2; + // break; + // case "BEV": + // startingPoint = 0.4; + // break; + // case "FCEV": + // startingPoint = 0.6; + // break; + // } + // + // //How many cars? + // var numVehicles = keysOfThisType.length; + // + // //Get a value between 0.0 and 1.0 + // var normalized = startingPoint + ((i / numVehicles) * spread); + // + // //Get that color on the spectrum + // return d3.interpolateCool(normalized); + // }) + // .append("title") //Make tooltip + // .text(function(d) { + // return d.key; + // }); + +//xxxxx + + + + + + }) .append("title") //Make tooltip .text(function(d) { From a492f1261aaa07825d5bdcd81fa57587fba7c460 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sun, 23 Apr 2017 10:17:44 -0700 Subject: [PATCH 71/85] Data fix, oops --- chapter_16/vehicle_sales_data.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chapter_16/vehicle_sales_data.csv b/chapter_16/vehicle_sales_data.csv index 1bdc5d1..441ad27 100644 --- a/chapter_16/vehicle_sales_data.csv +++ b/chapter_16/vehicle_sales_data.csv @@ -1,5 +1,5 @@ -Make,Honda,Toyota,Honda,Ford,Honda,Toyota,Lexus,Toyota,Lexus,Lexus,Nissan,Lexus,Saturn,Chevrolet,Chevrolet,Saturn,Dodge,Chevrolet,Ford,Mercedes-Benz,Mercedes-Benz,Mercedes-Benz,Mazda,BMW,BMW,Honda,Lincoln,Porsche,Lexus,Volkswagen,Infinity,Hyundai,Buick,Buick,Porsche,Kia,Acura,Ford,Lexus,Audi,Toyota,Volkswagen,Mercedes-Benz,Infiniti,Chevrolet,Infiniti,Nissan,Subaru,Acura,Lexus,Toyota,Acura,Kia,Hyundai,Chevrolet,Prius,Ford,Honda,Ford,Porsche,Cadillac,BMW,Porsche,Mercedes-Benz,Volvo,BMW,Hyundai,Audi,BMW,Mercedes-Benz,BMW,Mercedes-Benz,Kia,Nissan,Smart,Mitsubishi,BMW,Ford,Honda,Tesla,Toyota,Chevrolet,Fiat,BMW,Mercedes-Benz,Volkswagen,Kia,Tesla,Chevrolet,Hyundai,Toyota,Honda -Model,Insight,Prius,Civic,Escape,Accord,Highlander,RX 450h,Camry,GS 450h,HS 250h,Altima,LS 600hL,Vue,Tahoe,Malibu,Aura,Durango,Silverado,Fusion,S400,ML450,E320,Tribute,X6,Activehybrid3&5&7,CR-z,MKZ,Cayenne,CT 200h,Touareg,Q70 (M35h),Sonata,LaCrosse,Regal,Panamera S,Optima,ILX,C-Max,ES Hybrid,Q5 Hybrid,Avalon,Jetta,E400H,Q50,Impala Hybrid,QX60,Pathfinder Hybrid,XV,RLX,NX Hybrid,RAV4,NSX,Niro Hybrid,Ioniq Hybrid,Volt,PHEV,C-Max Energi,Accord,Fusion Energi,Panamera S E-Hybrid,ELR,i8,Cayenne S E-hybrid,S550 Plug,XC90 Plug In,X5,Sonata Plug In,A3 Plug In,3-series Plug-In,GLE 550e,7-series Plug-in,C350We,Optima Plug-in,LEAF,ED,I EV,Active E,Focus,Fit EV,Model S,RAV4 EV,Spark,500E,i3,B-Class,e-Golf,Soul EV,Model X,Bolt,Tucson,Mirai,Clarity +Make,Honda,Toyota,Honda,Ford,Honda,Toyota,Lexus,Toyota,Lexus,Lexus,Nissan,Lexus,Saturn,Chevrolet,Chevrolet,Saturn,Dodge,Chevrolet,Ford,Mercedes-Benz,Mercedes-Benz,Mercedes-Benz,Mazda,BMW,BMW,Honda,Lincoln,Porsche,Lexus,Volkswagen,Infinity,Hyundai,Buick,Buick,Porsche,Kia,Acura,Ford,Lexus,Audi,Toyota,Volkswagen,Mercedes-Benz,Infiniti,Chevrolet,Infiniti,Nissan,Subaru,Acura,Lexus,Toyota,Acura,Kia,Hyundai,Chevrolet,Toyota,Ford,Honda,Ford,Porsche,Cadillac,BMW,Porsche,Mercedes-Benz,Volvo,BMW,Hyundai,Audi,BMW,Mercedes-Benz,BMW,Mercedes-Benz,Kia,Nissan,Smart,Mitsubishi,BMW,Ford,Honda,Tesla,Toyota,Chevrolet,Fiat,BMW,Mercedes-Benz,Volkswagen,Kia,Tesla,Chevrolet,Hyundai,Toyota,Honda +Model,Insight,Prius,Civic,Escape,Accord,Highlander,RX 450h,Camry,GS 450h,HS 250h,Altima,LS 600hL,Vue,Tahoe,Malibu,Aura,Durango,Silverado,Fusion,S400,ML450,E320,Tribute,X6,Activehybrid3&5&7,CR-z,MKZ,Cayenne,CT 200h,Touareg,Q70 (M35h),Sonata,LaCrosse,Regal,Panamera S,Optima,ILX,C-Max,ES Hybrid,Q5 Hybrid,Avalon,Jetta,E400H,Q50,Impala Hybrid,QX60,Pathfinder Hybrid,XV,RLX,NX Hybrid,RAV4,NSX,Niro Hybrid,Ioniq Hybrid,Volt,Prius Plug-in,C-Max Energi,Accord,Fusion Energi,Panamera S E-Hybrid,ELR,i8,Cayenne S E-hybrid,S550 Plug,XC90 Plug In,X5,Sonata Plug In,A3 Plug In,3-series Plug-In,GLE 550e,7-series Plug-in,C350We,Optima Plug-in,LEAF,ED,I EV,Active E,Focus,Fit EV,Model S,RAV4 EV,Spark,500E,i3,B-Class,e-Golf,Soul EV,Model X,Bolt,Tucson,Mirai,Clarity Type,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,HEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,PHEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,BEV,FCEV,FCEV,FCEV 2005-01,7,5566,1169,908,805,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 2005-02,22,7078,1353,1092,855,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, From ef44661ad59e4e5bbd74d5b2a3e2b1d73baef2ac Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sun, 23 Apr 2017 10:58:38 -0700 Subject: [PATCH 72/85] Ch 16 progress --- chapter_16/08_zoom_to_vehicle.html | 202 +++++------------------------ 1 file changed, 29 insertions(+), 173 deletions(-) diff --git a/chapter_16/08_zoom_to_vehicle.html b/chapter_16/08_zoom_to_vehicle.html index 89c2020..5377e66 100644 --- a/chapter_16/08_zoom_to_vehicle.html +++ b/chapter_16/08_zoom_to_vehicle.html @@ -432,15 +432,14 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Get that color on the spectrum return d3.interpolateCool(normalized); }) -//xxxx .on("click", function(d) { //Which vehicle was clicked? var thisType = d.key; - console.log("You clicked " + d.key); //Fade out all other vehicle areas d3.selectAll("g#vehicles path") + .classed("unclickable", "true") //Prevent future clicks .filter(function(d) { //Filter out 'this' one if (d.key !== thisType) { return true; @@ -449,8 +448,6 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar .transition() .duration(1000) .attr("opacity", 0); - - //Zero-out baseline values, then transitioned into place. //Define area generator that will be used just this one time var singleVehicleArea = d3.area() @@ -460,181 +457,40 @@

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): Januar //Note y1 uses the raw 'sales' value for 'this' vehicle, //not the stacked data values (e.g., d[0] or d[1]). - d3.select(this) + //Use this new area generator to transition the area downward, + //to have a flat (zero) baseline. + var thisAreaTransition = d3.select(this) .transition() .delay(1000) .duration(1000) .attr("d", singleVehicleArea); - - - - // * A new y scale domain, based on the sales for this vehicle only, is calculated and set. - // * The clicked area and y axis are transitioned into place, to fit the new domain. + //Update y scale domain, based on the sales for this vehicle only + yScale.domain([ + 0, + d3.max(dataset, function(d) { + return d[thisType].sales; + }) + ]); - - - - // //Generate a new data set with all-zero values, - // //except for this vehicle's data - // var thisVehicleDataset = []; - // - // for (var i = 0; i < typeDataset.length; i++) { - // thisVehicleDataset[i] = { - // date: typeDataset[i].date, - // HEV: 0, - // PHEV: 0, - // BEV: 0, - // FCEV: 0, - // [thisType]: typeDataset[i][thisType] //Overwrites the appropriate zero value above - // } - // } - // - // // console.log(thisTypeDataset); - // - // //Stack the data (even though there's now just one "layer") and log it out - // var thisTypeSeries = typeStack(thisTypeDataset); - // // console.log(thisTypeSeries); - // - // //Bind the new data set to paths, overwriting old bound data. - // var paths = d3.selectAll("#types path") - // .data(thisTypeSeries, key) - // .classed("unclickable", "true"); - // - // //Transition areas into new positions (i.e., thisType's area - // //will go to a zero baseline; all others will flatten out). - // // - // //Store this transition in a new variable for later reference. - // var areaTransitions = paths.transition() - // .duration(1000) - // .attr("d", area); - // - // //Update scale - // yScale.domain([ - // 0, - // d3.max(thisTypeDataset, function(d) { - // var sum = 0; - // - // //Calculate the total (sum) of sales of this type, - // //ignoring the others (for now) - // sum += d[thisType]; - // - // return sum; - // }) - // ]); - // - // //Append this transition to the one already in progress - // //(from above). Transition areas to newly updated scale. - // areaTransitions.transition() - // .delay(200) - // .on("start", function() { - // - // //Transition axis to new scale concurrently - // d3.select("g.axis.y") - // .transition() - // .duration(1000) - // .call(yAxis); - // - // }) - // .duration(1000) - // .attr("d", area) - // .transition() - // .on("start", function() { - // //Make vehicles visible instantly, so - // //they are revealed when this fades out - // d3.selectAll("g#vehicles path") - // .attr("opacity", 1); - // }) - // .duration(1000) - // .attr("opacity", 0); - - - - // - // VEHICLES - // - - // //Get all possible keys (make + model), but toss out 'date' - // var keysAll = Object.keys(dataset[0]).slice(1); - // // console.log(keysAll); - // - // //Loop once for each key, and save out just the ones of thisType (e.g. BEVs) - // var keysOfThisType = []; - // for (var i = 0; i < keysAll.length; i++) { - // if (dataset[0][keysAll[i]].type == thisType) { - // keysOfThisType.push(keysAll[i]); - // } - // } - // // console.log(keysOfThisType); - // - // //Give the new keys to the stack function - // vehicleStack.keys(keysOfThisType) - // .value(function value(d, key) { - // return d[key].sales; - // }); - // - // //Stack the data and log it out - // var vehicleSeries = vehicleStack(dataset); - // // console.log(vehicleSeries); - // - // //Create areas for individual VEHICLES - // svg.select("g#vehicles") - // .selectAll("path") - // .data(vehicleSeries, key) - // .enter() - // .append("path") - // .attr("class", "area") - // .attr("opacity", 0) - // .attr("d", area) - // .attr("fill", function(d, i) { - // - // //Which vehicle is this? - // var thisKey = d.key; - // - // //What 'type' is this vehicle? - // var thisType = d[0].data[thisKey].type; - // // console.log(thisType); - // - // //Used to find a cool color below - // var spread = 0.2; - // var startingPoint; - // - // //Choose where in the color spectrum we start, based on type - // switch (thisType) { - // case "HEV": - // startingPoint = 0; - // break; - // case "PHEV": - // startingPoint = 0.2; - // break; - // case "BEV": - // startingPoint = 0.4; - // break; - // case "FCEV": - // startingPoint = 0.6; - // break; - // } - // - // //How many cars? - // var numVehicles = keysOfThisType.length; - // - // //Get a value between 0.0 and 1.0 - // var normalized = startingPoint + ((i / numVehicles) * spread); - // - // //Get that color on the spectrum - // return d3.interpolateCool(normalized); - // }) - // .append("title") //Make tooltip - // .text(function(d) { - // return d.key; - // }); - -//xxxxx - - - - - + //Transitions the clicked area and y axis into place, to fit the new domain + thisAreaTransition + .transition() + .duration(1000) + .attr("d", singleVehicleArea) + .on("start", function() { + + //Transition axis to new scale concurrently + d3.select("g.axis.y") + .transition() + .duration(1000) + .call(yAxis); + + }) + .on("end", function() { + //Restore clickability (is that a word?) + d3.select(this).classed("unclickable", "false"); + }); }) .append("title") //Make tooltip From 099e1b820b20bbdead8ffec8bd0bf2ee697e6844 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sun, 23 Apr 2017 19:59:03 -0700 Subject: [PATCH 73/85] New ch 16 example --- chapter_16/09_back_button.html | 730 +++++++++++++++++++++++++++++++++ 1 file changed, 730 insertions(+) create mode 100644 chapter_16/09_back_button.html diff --git a/chapter_16/09_back_button.html b/chapter_16/09_back_button.html new file mode 100644 index 0000000..2fd3e5b --- /dev/null +++ b/chapter_16/09_back_button.html @@ -0,0 +1,730 @@ + + + + + D3: Back button + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file From af341282b285b044c2859e9047ee16a4043b464c Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sun, 23 Apr 2017 21:40:06 -0700 Subject: [PATCH 74/85] Added new ch 16 example --- chapter_16/10_refine_styling.html | 755 ++++++++++++++++++++++++++++++ 1 file changed, 755 insertions(+) create mode 100644 chapter_16/10_refine_styling.html diff --git a/chapter_16/10_refine_styling.html b/chapter_16/10_refine_styling.html new file mode 100644 index 0000000..2ce00b4 --- /dev/null +++ b/chapter_16/10_refine_styling.html @@ -0,0 +1,755 @@ + + + + + D3: Refine styling + + + + +

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+ + + \ No newline at end of file From 6e516a12e717de6ce95905052782cf9c19ee562a Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 24 Apr 2017 10:26:54 -0700 Subject: [PATCH 75/85] Final example woohoo --- chapter_16/11_context.html | 834 +++++++++++++++++++++++++++++++++++ chapter_16/z22_bar_page.html | 440 ------------------ 2 files changed, 834 insertions(+), 440 deletions(-) create mode 100644 chapter_16/11_context.html delete mode 100644 chapter_16/z22_bar_page.html diff --git a/chapter_16/11_context.html b/chapter_16/11_context.html new file mode 100644 index 0000000..5fc0111 --- /dev/null +++ b/chapter_16/11_context.html @@ -0,0 +1,834 @@ + + + + + D3: Context + + + + + + +
+ +

U.S. Electric-Drive Vehicle Sales

+ +

Rerum culpa qui libero. Non quidem suscipit facere ea totam. Sed ut reprehenderit non. Consequuntur alias minima qui saepe enim. Voluptatem quia quia eligendi temporibus dolor voluptas voluptatem recusandae. Quia minima delectus aliquid totam voluptatem enim alias quas.

+ +

+

Monthly Number of Electric-Drive Vehicles Sold in the U.S. (by Type): January 2005–Feburary 2017

+
+ +

Reiciendis reiciendis quia labore porro ratione. Asperiores est ipsam voluptate. Itaque in magni qui veritatis aliquam fugiat. Et qui aliquid et. Assumenda qui et quis ut. Dolores aut ea fuga corporis enim. Corporis iusto facere quidem architecto rerum pariatur. Libero nam et cupiditate quibusdam.

+ +

Est voluptates sint rerum nostrum dignissimos. Accusantium eius voluptate et libero dignissimos. Aspernatur eum asperiores et rerum. Consequatur et in neque accusantium ipsam officiis. Eligendi ex quia praesentium voluptate nihil suscipit.

+ + + +
+ + + + \ No newline at end of file diff --git a/chapter_16/z22_bar_page.html b/chapter_16/z22_bar_page.html deleted file mode 100644 index e0c0480..0000000 --- a/chapter_16/z22_bar_page.html +++ /dev/null @@ -1,440 +0,0 @@ - - - - - D3: Placing charts in a larger page layout - - - - - - - - -
- -

Five New Data Insights You Have to See to Believe

- -

You won’t believe your eyes when you realize what these charts are telling you. The numbers don’t lie, and sometimes facing the facts can cause a shock. No one could have predicted this, and no one knew it was true until we published these innovative visualizations, thereby proving definitively that a picture is worth a thousand words. (Edit the source to add more cliches here.)

- -
-

Total sales by employee in July 2015

-
- -
-

Total bonuses by employee in July 2015

-
- -
- -
- - - -
- - - - - - \ No newline at end of file From d624a722ec40911f61ee9228b344dcf363b0306a Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 12 May 2017 11:01:51 -0700 Subject: [PATCH 76/85] Renamed rScale to aScale when using sq root --- chapter_07/08_scaled_plot_sqrt_scale.html | 4 ++-- chapter_08/01_axes.html | 4 ++-- chapter_08/02_axes_bottom.html | 4 ++-- chapter_08/03_axes_clean.html | 4 ++-- chapter_08/04_axes_y.html | 4 ++-- chapter_08/05_axes_random.html | 4 ++-- chapter_08/06_axes_no_labels.html | 4 ++-- chapter_08/07_axes_format.html | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/chapter_07/08_scaled_plot_sqrt_scale.html b/chapter_07/08_scaled_plot_sqrt_scale.html index 32e26c0..b713036 100644 --- a/chapter_07/08_scaled_plot_sqrt_scale.html +++ b/chapter_07/08_scaled_plot_sqrt_scale.html @@ -31,7 +31,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -53,7 +53,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); //Create labels diff --git a/chapter_08/01_axes.html b/chapter_08/01_axes.html index 7729dbd..87217c8 100644 --- a/chapter_08/01_axes.html +++ b/chapter_08/01_axes.html @@ -31,7 +31,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -57,7 +57,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); //Create labels diff --git a/chapter_08/02_axes_bottom.html b/chapter_08/02_axes_bottom.html index caf8c30..a252a90 100644 --- a/chapter_08/02_axes_bottom.html +++ b/chapter_08/02_axes_bottom.html @@ -31,7 +31,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -57,7 +57,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); //Create labels diff --git a/chapter_08/03_axes_clean.html b/chapter_08/03_axes_clean.html index 6a7ef47..200bbdc 100644 --- a/chapter_08/03_axes_clean.html +++ b/chapter_08/03_axes_clean.html @@ -31,7 +31,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -58,7 +58,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); //Create labels diff --git a/chapter_08/04_axes_y.html b/chapter_08/04_axes_y.html index 0d2d94c..4386025 100644 --- a/chapter_08/04_axes_y.html +++ b/chapter_08/04_axes_y.html @@ -31,7 +31,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -63,7 +63,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); //Create labels diff --git a/chapter_08/05_axes_random.html b/chapter_08/05_axes_random.html index 450285b..0e19860 100644 --- a/chapter_08/05_axes_random.html +++ b/chapter_08/05_axes_random.html @@ -45,7 +45,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -77,7 +77,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); //Create labels diff --git a/chapter_08/06_axes_no_labels.html b/chapter_08/06_axes_no_labels.html index dc21011..83a5bb3 100644 --- a/chapter_08/06_axes_no_labels.html +++ b/chapter_08/06_axes_no_labels.html @@ -45,7 +45,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -77,7 +77,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); /* diff --git a/chapter_08/07_axes_format.html b/chapter_08/07_axes_format.html index 38eed3b..8165b90 100644 --- a/chapter_08/07_axes_format.html +++ b/chapter_08/07_axes_format.html @@ -45,7 +45,7 @@ .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([h - padding, padding]); - var rScale = d3.scaleSqrt() + var aScale = d3.scaleSqrt() .domain([0, d3.max(dataset, function(d) { return d[1]; })]) .range([0, 10]); @@ -81,7 +81,7 @@ return yScale(d[1]); }) .attr("r", function(d) { - return rScale(d[1]); + return aScale(d[1]); }); /* From 837225d888b42e0312fad33db08949660a1b4ed2 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 12 May 2017 11:46:21 -0700 Subject: [PATCH 77/85] Renamed eaches to ons --- chapter_09/17_randomized_data.html | 2 +- chapter_09/{21_each.html => 21_on.html} | 2 +- ...2_each_combo_transition.html => 22_on_combo_transition.html} | 2 +- ...ombo_transition_chained.html => 23_chained_transitions.html} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename chapter_09/{21_each.html => 21_on.html} (98%) rename chapter_09/{22_each_combo_transition.html => 22_on_combo_transition.html} (98%) rename chapter_09/{23_each_combo_transition_chained.html => 23_chained_transitions.html} (98%) diff --git a/chapter_09/17_randomized_data.html b/chapter_09/17_randomized_data.html index fd9aee9..b04f28a 100644 --- a/chapter_09/17_randomized_data.html +++ b/chapter_09/17_randomized_data.html @@ -85,7 +85,7 @@ var numValues = dataset.length; //Count original length of dataset dataset = []; //Initialize empty array for (var i = 0; i < numValues; i++) { //Loop numValues times - var newNumber = Math.floor(Math.random() * 25); //New random integer (0-25) + var newNumber = Math.floor(Math.random() * 25); //New random integer (0-24) dataset.push(newNumber); //Add new number to array } diff --git a/chapter_09/21_each.html b/chapter_09/21_on.html similarity index 98% rename from chapter_09/21_each.html rename to chapter_09/21_on.html index 47ca336..3287adf 100644 --- a/chapter_09/21_each.html +++ b/chapter_09/21_on.html @@ -2,7 +2,7 @@ - D3: Using each() to start and end transitions + D3: Using on() at transitions' start and end -

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005–Feburary 2017

+

Monthly Number of Electric-Drive Vehicles Sold in the U.S.: January 2005–February 2017