(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o b ? 1 : a >= b ? 0 : NaN; } function bisector(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; function descending(a, b) { return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; } function number(x) { return x === null ? NaN : +x; } function variance(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); } function deviation(array, f) { var v = variance(array, f); return v ? Math.sqrt(v) : v; } function extent(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; function constant(x) { return function() { return x; }; } function identity(x) { return x; } function range(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); function ticks(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; } function sturges(values) { return Math.ceil(Math.log(values.length) / Math.LN2) + 1; } function histogram() { 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(_), histogram) : value; }; histogram.domain = function(_) { return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; }; histogram.thresholds = function(_) { return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; }; return histogram; } function quantile(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); } function freedmanDiaconis(values, min, max) { values = map.call(values, number).sort(ascending); return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3))); } function scott(values, min, max) { return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); } function max(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; } function mean(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; } function median(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 quantile(numbers.sort(ascending), 0.5); } function merge(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; } function min(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; } function pairs(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; } function permute(array, indexes) { var i = indexes.length, permutes = new Array(i); while (i--) permutes[i] = array[indexes[i]]; return permutes; } function scan(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; } function shuffle(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; } function sum(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; } function transpose(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; } function zip() { return transpose(arguments); } 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 = quantile; 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; Object.defineProperty(exports, '__esModule', { value: true }); })); },{}],3:[function(require,module,exports){ // https://d3js.org/d3-collection/ Version 1.0.1. 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 prefix = "$"; function Map() {} Map.prototype = map.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(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; } function nest() { 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(), 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(); } function setMap(map, key, value) { map.set(key, value); } function Set() {} var proto = map.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; } function keys(map) { var keys = []; for (var key in map) keys.push(key); return keys; } function values(map) { var values = []; for (var key in map) values.push(map[key]); return values; } function entries(map) { var entries = []; for (var key in map) entries.push({key: key, value: map[key]}); return entries; } exports.nest = nest; exports.set = set; exports.map = map; exports.keys = keys; exports.values = values; exports.entries = entries; Object.defineProperty(exports, '__esModule', { value: true }); })); },{}],4:[function(require,module,exports){ // https://d3js.org/d3-color/ Version 1.0.1. 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'; function define(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 ); } })); exports.color = color; exports.rgb = rgb; exports.hsl = hsl; exports.lab = lab; exports.hcl = hcl; exports.cubehelix = cubehelix; Object.defineProperty(exports, '__esModule', { value: true }); })); },{}],5:[function(require,module,exports){ // http://geoexamples.com/d3-composite-projections/ Version 1.0.0. Copyright 2016 Roger Veciana i Rovira. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-geo'), require('d3-path')) : typeof define === 'function' && define.amd ? define(['exports', 'd3-geo', 'd3-path'], factory) : (factory((global.d3 = global.d3 || {}),global.d3,global.d3)); }(this, function (exports,d3Geo,d3Path) { 'use strict'; var epsilon = 1e-6; // 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. Also works quite well at 960×600 with scale 1285. 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 function albersUsa() { var cache, cacheStream, lower48 = d3Geo.geoAlbers(), lower48Point, alaska = d3Geo.geoConicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 hawaii = d3Geo.geoConicEqualArea().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 albersUsa; }; 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, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]]) .stream(pointStream); hawaiiPoint = hawaii .translate([x - 0.205 * k, y + 0.212 * k]) .clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]]) .stream(pointStream); return albersUsa; }; albersUsa.drawCompositionBorders = function(context) { var hawaii1 = lower48([-102.91, 26.3]); var hawaii2 = lower48([-104.0, 27.5]); var hawaii3 = lower48([-108.0, 29.1]); var hawaii4 = lower48([-110.0, 29.1]); var alaska1 = lower48([-110.0, 26.7]); var alaska2 = lower48([-112.8, 27.6]); var alaska3 = lower48([-114.3, 30.6]); var alaska4 = lower48([-119.3, 30.1]); context.moveTo(hawaii1[0], hawaii1[1]); context.lineTo(hawaii2[0], hawaii2[1]); context.lineTo(hawaii3[0], hawaii3[1]); context.lineTo(hawaii4[0], hawaii4[1]); context.moveTo(alaska1[0], alaska1[1]); context.lineTo(alaska2[0], alaska2[1]); context.lineTo(alaska3[0], alaska3[1]); context.lineTo(alaska4[0], alaska4[1]); }; albersUsa.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return albersUsa.scale(1070); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$1(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. Also works quite well at 960×600 with scale 1285. 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 function albersUsaTerritories() { var cache, cacheStream, lower48 = d3Geo.geoAlbers(), lower48Point, alaska = d3Geo.geoConicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 hawaii = d3Geo.geoConicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 puertoRico = d3Geo.geoConicEqualArea().rotate([66, 0]).center([0, 18]).parallels([8, 18]), puertoRicoPoint, //Taken from https://bl.ocks.org/mbostock/5629120 samoa = d3Geo.geoEquirectangular().rotate([173, 14]), samoaPoint, // EPSG:4169 guam = d3Geo.geoEquirectangular().rotate([-145, -16.8]), guamPoint, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var puertoRicoBbox = [[-68.3, 19], [-63.9, 17]]; var samoaBbox = [[-171, -14], [-168, -14.8]]; var guamBbox = [[144, 20.8], [146.5, 12.7]]; */ 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) || (puertoRicoPoint.point(x, y), point) || (samoaPoint.point(x, y), point) || (guamPoint.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; /* //How are the return values calculated: console.info("******"); var c0 = puertoRico(puertoRicoBbox[0]); var x0 = (c0[0] - t[0]) / k; var y0 = (c0[1] - t[1]) / k; console.info("p0 puertoRico", x0 + ' - ' + y0); var c1 = puertoRico(puertoRicoBbox[1]); var x1 = (c1[0] - t[0]) / k; var y1 = (c1[1] - t[1]) / k; console.info("p1 puertoRico", x1 + ' - ' + y1); c0 = samoa(samoaBbox[0]); x0 = (c0[0] - t[0]) / k; y0 = (c0[1] - t[1]) / k; console.info("p0 samoa", x0 + ' - ' + y0); c1 = samoa(samoaBbox[1]); x1 = (c1[0] - t[0]) / k; y1 = (c1[1] - t[1]) / k; console.info("p1 samoa", x1 + ' - ' + y1); c0 = guam(guamBbox[0]); x0 = (c0[0] - t[0]) / k; y0 = (c0[1] - t[1]) / k; console.info("p0 guam", x0 + ' - ' + y0); c1 = guam(guamBbox[1]); x1 = (c1[0] - t[0]) / k; y1 = (c1[1] - t[1]) / k; console.info("p1 guam", x1 + ' - ' + y1); */ 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 : y >= 0.2064 && y < 0.2413 && x >= 0.312 && x < 0.385 ? puertoRico : y >= 0.09 && y < 0.1197 && x >= -0.4243 && x < -0.3232 ? samoa : y >= -0.0518 && y < 0.0895 && x >= -0.4243 && x < -0.3824 ? guam : lower48).invert(coordinates); }; albersUsa.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$1([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream), puertoRico.stream(stream), samoa.stream(stream), guam.stream(stream)]); }; albersUsa.precision = function(_) { if (!arguments.length) {return lower48.precision();} lower48.precision(_); alaska.precision(_); hawaii.precision(_); puertoRico.precision(_); samoa.precision(_); guam.precision(_); return albersUsa; }; albersUsa.scale = function(_) { if (!arguments.length) {return lower48.scale();} lower48.scale(_); alaska.scale(_ * 0.35); hawaii.scale(_); puertoRico.scale(_); samoa.scale(_* 2); guam.scale(_); return albersUsa.translate(lower48.translate()); }; albersUsa.translate = function(_) { if (!arguments.length) {return lower48.translate();} var k = lower48.scale(), x = +_[0], y = +_[1]; /* var c0 = puertoRico.translate([x + 0.350 * k, y + 0.224 * k])(puertoRicoBbox[0]); var x0 = (x - c0[0]) / k; var y0 = (y - c0[1]) / k; var c1 = puertoRico.translate([x + 0.350 * k, y + 0.224 * k])(puertoRicoBbox[1]); var x1 = (x - c1[0]) / k; var y1 = (y - c1[1]) / k; console.info('puertoRico: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); c0 = samoa.translate([x - 0.492 * k, y + 0.09 * k])(samoaBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = samoa.translate([x - 0.492 * k, y + 0.09 * k])(samoaBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('samoa: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); c0 = guam.translate([x - 0.408 * k, y + 0.018 * k])(guamBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = guam.translate([x - 0.408 * k, y + 0.018 * k])(guamBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('guam: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); */ 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, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.233 * k - epsilon]]) .stream(pointStream); hawaiiPoint = hawaii .translate([x - 0.205 * k, y + 0.212 * k]) .clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.233 * k - epsilon]]) .stream(pointStream); puertoRicoPoint = puertoRico .translate([x + 0.350 * k, y + 0.224 * k]) .clipExtent([[x + 0.312 * k + epsilon, y + 0.2064 * k + epsilon],[x + 0.385 * k - epsilon, y + 0.233 * k - epsilon]]) .stream(pointStream); samoaPoint = samoa .translate([x - 0.492 * k, y + 0.09 * k]) .clipExtent([[x - 0.4243 * k + epsilon, y + 0.0903 * k + epsilon],[x - 0.3233 * k - epsilon, y + 0.1197 * k - epsilon]]) .stream(pointStream); guamPoint = guam .translate([x - 0.408 * k, y + 0.018 * k]) .clipExtent([[x - 0.4244 * k + epsilon, y - 0.0519 * k + epsilon],[x - 0.3824 * k - epsilon, y + 0.0895 * k - epsilon]]) .stream(pointStream); return albersUsa; }; albersUsa.drawCompositionBorders = function(context) { /* console.info("CLIP EXTENT hawaii: ", hawaii.clipExtent()); console.info("UL BBOX:", lower48.invert([hawaii.clipExtent()[0][0], hawaii.clipExtent()[0][1]])); console.info("UR BBOX:", lower48.invert([hawaii.clipExtent()[1][0], hawaii.clipExtent()[0][1]])); console.info("LD BBOX:", lower48.invert([hawaii.clipExtent()[1][0], hawaii.clipExtent()[1][1]])); console.info("LL BBOX:", lower48.invert([hawaii.clipExtent()[0][0], hawaii.clipExtent()[1][1]])); console.info("CLIP EXTENT alaska: ", alaska.clipExtent()); console.info("UL BBOX:", lower48.invert([alaska.clipExtent()[0][0], alaska.clipExtent()[0][1]])); console.info("UR BBOX:", lower48.invert([alaska.clipExtent()[1][0], alaska.clipExtent()[0][1]])); console.info("LD BBOX:", lower48.invert([alaska.clipExtent()[1][0], alaska.clipExtent()[1][1]])); console.info("LL BBOX:", lower48.invert([alaska.clipExtent()[0][0], alaska.clipExtent()[1][1]])); console.info("CLIP EXTENT puertoRico: ", puertoRico.clipExtent()); console.info("UL BBOX:", lower48.invert([puertoRico.clipExtent()[0][0], puertoRico.clipExtent()[0][1]])); console.info("UR BBOX:", lower48.invert([puertoRico.clipExtent()[1][0], puertoRico.clipExtent()[0][1]])); console.info("LD BBOX:", lower48.invert([puertoRico.clipExtent()[1][0], puertoRico.clipExtent()[1][1]])); console.info("LL BBOX:", lower48.invert([puertoRico.clipExtent()[0][0], puertoRico.clipExtent()[1][1]])); console.info("CLIP EXTENT samoa: ", samoa.clipExtent()); console.info("UL BBOX:", lower48.invert([samoa.clipExtent()[0][0], samoa.clipExtent()[0][1]])); console.info("UR BBOX:", lower48.invert([samoa.clipExtent()[1][0], samoa.clipExtent()[0][1]])); console.info("LD BBOX:", lower48.invert([samoa.clipExtent()[1][0], samoa.clipExtent()[1][1]])); console.info("LL BBOX:", lower48.invert([samoa.clipExtent()[0][0], samoa.clipExtent()[1][1]])); console.info("CLIP EXTENT guam: ", guam.clipExtent()); console.info("UL BBOX:", lower48.invert([guam.clipExtent()[0][0], guam.clipExtent()[0][1]])); console.info("UR BBOX:", lower48.invert([guam.clipExtent()[1][0], guam.clipExtent()[0][1]])); console.info("LD BBOX:", lower48.invert([guam.clipExtent()[1][0], guam.clipExtent()[1][1]])); console.info("LL BBOX:", lower48.invert([guam.clipExtent()[0][0], guam.clipExtent()[1][1]])); */ var ulhawaii = lower48([-110.4641, 28.2805]); var urhawaii = lower48([-104.0597, 28.9528]); var ldhawaii = lower48([-103.7049, 25.1031]); var llhawaii = lower48([-109.8337, 24.4531]); var ulalaska = lower48([ -124.4745, 28.1407]); var uralaska = lower48([ -110.931, 30.8844]); var ldalaska = lower48([-109.8337, 24.4531]); var llalaska = lower48([-122.4628, 21.8562]); var ulpuertoRico = lower48([-76.8579, 25.1544]); var urpuertoRico = lower48([-72.429, 24.2097]); var ldpuertoRico = lower48([-72.8265, 22.7056]); var llpuertoRico = lower48([-77.1852, 23.6392]); var ulsamoa = lower48([-125.0093, 29.7791]); var ursamoa = lower48([-118.5193, 31.3262]); var ldsamoa = lower48([-118.064, 29.6912]); var llsamoa = lower48([-124.4369, 28.169]); var ulguam = lower48([-128.1314, 37.4582]); var urguam = lower48([-125.2132, 38.214]); var ldguam = lower48([-122.3616, 30.5115]); var llguam = lower48([-125.0315, 29.8211]); context.moveTo(ulhawaii[0], ulhawaii[1]); context.lineTo(urhawaii[0], urhawaii[1]); context.lineTo(ldhawaii[0], ldhawaii[1]); context.lineTo(ldhawaii[0], ldhawaii[1]); context.lineTo(llhawaii[0], llhawaii[1]); context.closePath(); context.moveTo(ulalaska[0], ulalaska[1]); context.lineTo(uralaska[0], uralaska[1]); context.lineTo(ldalaska[0], ldalaska[1]); context.lineTo(ldalaska[0], ldalaska[1]); context.lineTo(llalaska[0], llalaska[1]); context.closePath(); context.moveTo(ulpuertoRico[0], ulpuertoRico[1]); context.lineTo(urpuertoRico[0], urpuertoRico[1]); context.lineTo(ldpuertoRico[0], ldpuertoRico[1]); context.lineTo(ldpuertoRico[0], ldpuertoRico[1]); context.lineTo(llpuertoRico[0], llpuertoRico[1]); context.closePath(); context.moveTo(ulsamoa[0], ulsamoa[1]); context.lineTo(ursamoa[0], ursamoa[1]); context.lineTo(ldsamoa[0], ldsamoa[1]); context.lineTo(ldsamoa[0], ldsamoa[1]); context.lineTo(llsamoa[0], llsamoa[1]); context.closePath(); context.moveTo(ulguam[0], ulguam[1]); context.lineTo(urguam[0], urguam[1]); context.lineTo(ldguam[0], ldguam[1]); context.lineTo(ldguam[0], ldguam[1]); context.lineTo(llguam[0], llguam[1]); context.closePath(); }; albersUsa.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return albersUsa.scale(1070); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$2(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 Spain, configured by default for 960×500. function conicConformalSpain() { var cache, cacheStream, iberianPeninsule = d3Geo.geoConicConformal().rotate([5, -38.6]).parallels([0,60]), iberianPeninsulePoint, canaryIslands = d3Geo.geoConicConformal().rotate([5, -38.6]).parallels([0,60]), canaryIslandsPoint, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var iberianPeninsuleBbox = [[-11, 46], [4, 35]]; var canaryIslandsBbox = [[-19.0, 28.85], [-12.7, 28.1]]; */ function conicConformalSpain(coordinates) { var x = coordinates[0], y = coordinates[1]; return point = null, (iberianPeninsulePoint.point(x, y), point) || (canaryIslandsPoint.point(x, y), point); } conicConformalSpain.invert = function(coordinates) { var k = iberianPeninsule.scale(), t = iberianPeninsule.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; /* //How are the return values calculated: var c0 = canaryIslands(canaryIslandsBbox[0]); var x0 = (c0[0] - t[0]) / k; var y0 = (c0[1] - t[1]) / k; console.info("p0 canary islands", x0 + ' - ' + y0); var c1 = canaryIslands(canaryIslandsBbox[1]); var x1 = (c1[0] - t[0]) / k; var y1 = (c1[1] - t[1]) / k; console.info("p1 canary islands", x1 + ' - ' + y1); */ return (y >= 0.05346 && y< 0.0897 && x >= -0.13388 && x < -0.0322 ? canaryIslands : iberianPeninsule).invert(coordinates); }; conicConformalSpain.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$2([iberianPeninsule.stream(cacheStream = stream), canaryIslands.stream(stream)]); }; conicConformalSpain.precision = function(_) { if (!arguments.length) {return iberianPeninsule.precision();} iberianPeninsule.precision(_); canaryIslands.precision(_); return conicConformalSpain; }; conicConformalSpain.scale = function(_) { if (!arguments.length) {return iberianPeninsule.scale();} iberianPeninsule.scale(_); canaryIslands.scale(_); return conicConformalSpain.translate(iberianPeninsule.translate()); }; conicConformalSpain.translate = function(_) { if (!arguments.length) {return iberianPeninsule.translate();} var k = iberianPeninsule.scale(), x = +_[0], y = +_[1]; /* var c0 = iberianPeninsule(iberianPeninsuleBbox[0]); var x0 = (x - c0[0]) / k; var y0 = (y - c0[1]) / k; var c1 = iberianPeninsule(iberianPeninsuleBbox[1]); var x1 = (x - c1[0]) / k; var y1 = (y - c1[1]) / k; console.info('Iberian Peninsula: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); c0 = canaryIslands.translate([x + 0.1 * k, y - 0.094 * k])(canaryIslandsBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = canaryIslands.translate([x + 0.1 * k, y - 0.094 * k])(canaryIslandsBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('Canry Islands: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); */ iberianPeninsulePoint = iberianPeninsule .translate(_) .clipExtent([[x - 0.06857 * k, y - 0.1288 * k],[x + 0.13249 * k, y + 0.05292 * k]]) .stream(pointStream); canaryIslandsPoint = canaryIslands .translate([x + 0.1 * k, y - 0.094 * k]) .clipExtent([[x - 0.1331 * k + epsilon, y + 0.053457 * k + epsilon],[x - 0.0354 * k - epsilon, y + 0.08969 * k - epsilon]]) .stream(pointStream); return conicConformalSpain; }; conicConformalSpain.drawCompositionBorders = function(context) { /* console.info("CLIP EXTENT: ", canaryIslands.clipExtent()); console.info("UL BBOX:", iberianPeninsule.invert([canaryIslands.clipExtent()[0][0], canaryIslands.clipExtent()[0][1]])); console.info("UR BBOX:", iberianPeninsule.invert([canaryIslands.clipExtent()[1][0], canaryIslands.clipExtent()[0][1]])); console.info("LD BBOX:", iberianPeninsule.invert([canaryIslands.clipExtent()[1][0], canaryIslands.clipExtent()[1][1]])); */ var ulCanaryIslands = iberianPeninsule([-14.0346750522884, 34.96500729877966]); var urCanaryIslands = iberianPeninsule([-7.4208899681602025, 35.53698899616862]); var ldCanaryIslands = iberianPeninsule([-7.314827535125545, 33.54359498636456]); context.moveTo(ulCanaryIslands[0], ulCanaryIslands[1]); context.lineTo(urCanaryIslands[0], urCanaryIslands[1]); context.lineTo(ldCanaryIslands[0], ldCanaryIslands[1]); }; conicConformalSpain.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return conicConformalSpain.scale(2700); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$3(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 Portugal, configured by default for 960×500. function conicConformalPortugal() { var cache, cacheStream, iberianPeninsule = d3Geo.geoConicConformal().rotate([10, -39.3]).parallels([0, 60]), iberianPeninsulePoint, madeira = d3Geo.geoConicConformal().rotate([17, -32.7]).parallels([0, 60]), madeiraPoint, azores = d3Geo.geoConicConformal().rotate([27.8, -38.6]).parallels([0, 60]), azoresPoint, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var iberianPeninsuleBbox = [[-11, 46], [4, 34]]; var madeiraBbox = [[-17.85, 33.6], [-16, 32.02]]; var azoresBbox = [[-32, 40.529], [-23.98, 35.75]]; */ function conicConformalPortugal(coordinates) { var x = coordinates[0], y = coordinates[1]; return point = null, (iberianPeninsulePoint.point(x, y), point) || (madeiraPoint.point(x, y), point) || (azoresPoint.point(x, y), point); } conicConformalPortugal.invert = function(coordinates) { var k = iberianPeninsule.scale(), t = iberianPeninsule.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; /* //How are the return values calculated: console.info("******"); var c0 = madeira(madeiraBbox[0]); var x0 = (c0[0] - t[0]) / k; var y0 = (c0[1] - t[1]) / k; console.info("p0 madeira", x0 + ' - ' + y0); var c1 = madeira(madeiraBbox[1]); var x1 = (c1[0] - t[0]) / k; var y1 = (c1[1] - t[1]) / k; console.info("p1 madeira", x1 + ' - ' + y1); c0 = azores(azoresBbox[0]); x0 = (c0[0] - t[0]) / k; y0 = (c0[1] - t[1]) / k; console.info("p0 azores", x0 + ' - ' + y0); c1 = azores(azoresBbox[1]); x1 = (c1[0] - t[0]) / k; y1 = (c1[1] - t[1]) / k; console.info("p1 azores", x1 + ' - ' + y1); */ return (y >= 0.0093 && y< 0.03678 && x >= -0.03875 && x < -0.0116 ? madeira : y >= -0.0412 && y< 0.0091 && x >= -0.07782 && x < -0.01166 ? azores : iberianPeninsule).invert(coordinates); }; conicConformalPortugal.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$3([iberianPeninsule.stream(cacheStream = stream), madeira.stream(stream), azores.stream(stream)]); }; conicConformalPortugal.precision = function(_) { if (!arguments.length) {return iberianPeninsule.precision();} iberianPeninsule.precision(_); madeira.precision(_); azores.precision(_); return conicConformalPortugal; }; conicConformalPortugal.scale = function(_) { if (!arguments.length) {return iberianPeninsule.scale();} iberianPeninsule.scale(_); madeira.scale(_); azores.scale(_ * 0.6); return conicConformalPortugal.translate(iberianPeninsule.translate()); }; conicConformalPortugal.translate = function(_) { if (!arguments.length) {return iberianPeninsule.translate();} var k = iberianPeninsule.scale(), x = +_[0], y = +_[1]; /* var c0 = iberianPeninsule(iberianPeninsuleBbox[0]); var x0 = (x - c0[0]) / k; var y0 = (y - c0[1]) / k; var c1 = iberianPeninsule(iberianPeninsuleBbox[1]); var x1 = (x - c1[0]) / k; var y1 = (y - c1[1]) / k; console.info('Iberian Peninsula: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k]])'); c0 = madeira.translate([x - 0.0265 * k, y + 0.025 * k])(madeiraBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = madeira.translate([x - 0.0265 * k, y + 0.025 * k])(madeiraBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('Madeira: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); c0 = azores.translate([x - 0.045 * k, y + -0.02 * k])(azoresBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = azores.translate([x - 0.045 * k, y + -0.02 * k])(azoresBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('Azores: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); */ iberianPeninsulePoint = iberianPeninsule .translate(_) .clipExtent([[x - 0.0115 * k, y - 0.1138 * k],[x +0.2105 * k, y +0.0673 * k]]) .stream(pointStream); madeiraPoint = madeira .translate([x - 0.0265 * k, y + 0.025 * k]) .clipExtent([[x - 0.0388 * k + epsilon, y + 0.0093 * k + epsilon],[x - 0.0116 * k - epsilon, y + 0.0368 * k - epsilon]]) .stream(pointStream); azoresPoint = azores .translate([x - 0.045 * k, y + -0.02 * k]) .clipExtent([[x - 0.0778 * k + epsilon, y - 0.0413 * k + epsilon],[x - 0.0117 * k - epsilon, y + 0.0091 * k - epsilon]]) .stream(pointStream); return conicConformalPortugal; }; conicConformalPortugal.drawCompositionBorders = function(context) { /* console.info("CLIP EXTENT MADEIRA: ", madeira.clipExtent()); console.info("UL BBOX:", iberianPeninsule.invert([madeira.clipExtent()[0][0], madeira.clipExtent()[0][1]])); console.info("UR BBOX:", iberianPeninsule.invert([madeira.clipExtent()[1][0], madeira.clipExtent()[0][1]])); console.info("LD BBOX:", iberianPeninsule.invert([madeira.clipExtent()[1][0], madeira.clipExtent()[1][1]])); console.info("LL BBOX:", iberianPeninsule.invert([madeira.clipExtent()[0][0], madeira.clipExtent()[1][1]])); console.info("CLIP EXTENT AZORES: ", azores.clipExtent()); console.info("UL BBOX:", iberianPeninsule.invert([azores.clipExtent()[0][0], azores.clipExtent()[0][1]])); console.info("UR BBOX:", iberianPeninsule.invert([azores.clipExtent()[1][0], azores.clipExtent()[0][1]])); console.info("LD BBOX:", iberianPeninsule.invert([azores.clipExtent()[1][0], azores.clipExtent()[1][1]])); console.info("LL BBOX:", iberianPeninsule.invert([azores.clipExtent()[0][0], azores.clipExtent()[1][1]])); */ var ulmadeira = iberianPeninsule([-12.8351, 38.7113]); var urmadeira = iberianPeninsule([-10.8482, 38.7633]); var ldmadeira = iberianPeninsule([-10.8181, 37.2072]); var llmadeira = iberianPeninsule([-12.7345, 37.1573]); var ulazores = iberianPeninsule([-16.0753, 41.4436]); var urazores = iberianPeninsule([-10.9168, 41.6861]); var ldazores = iberianPeninsule([-10.8557, 38.7747]); var llazores = iberianPeninsule([-15.6728, 38.5505]); context.moveTo(ulmadeira[0], ulmadeira[1]); context.lineTo(urmadeira[0], urmadeira[1]); context.lineTo(ldmadeira[0], ldmadeira[1]); context.lineTo(ldmadeira[0], ldmadeira[1]); context.lineTo(llmadeira[0], llmadeira[1]); context.closePath(); context.moveTo(ulazores[0], ulazores[1]); context.lineTo(urazores[0], urazores[1]); context.lineTo(ldazores[0], ldazores[1]); context.lineTo(ldazores[0], ldazores[1]); context.lineTo(llazores[0], llazores[1]); context.closePath(); }; conicConformalPortugal.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return conicConformalPortugal.scale(4200); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$4(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 Ecuador, configured by default for 960×500. function mercatorEcuador() { var cache, cacheStream, mainland = d3Geo.geoMercator().rotate([80, 1.5]), mainlandPoint, galapagos = d3Geo.geoMercator().rotate([90.73, 1]), galapagosPoint, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var mainlandBbox = [[-81.5, 2.7], [-70.0, -6.0]]; var galapagosBbox = [[-92.2, 0.58], [-88.8, -1.8]]; */ function mercatorEcuador(coordinates) { var x = coordinates[0], y = coordinates[1]; return point = null, (mainlandPoint.point(x, y), point) || (galapagosPoint.point(x, y), point); } mercatorEcuador.invert = function(coordinates) { var k = mainland.scale(), t = mainland.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; /* //How are the return values calculated: var c0 = galapagos(galapagosBbox[0]); var x0 = (c0[0] - t[0]) / k; var y0 = (c0[1] - t[1]) / k; console.info("p0 galapagos", x0 + ' - ' + y0); var c1 = galapagos(galapagosBbox[1]); var x1 = (c1[0] - t[0]) / k; var y1 = (c1[1] - t[1]) / k; console.info("p1 galapagos", x1 + ' - ' + y1); */ return (y >= -0.0676 && y< -0.026 && x >= -0.0857 && x < -0.0263 ? galapagos : mainland).invert(coordinates); }; mercatorEcuador.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$4([mainland.stream(cacheStream = stream), galapagos.stream(stream)]); }; mercatorEcuador.precision = function(_) { if (!arguments.length) {return mainland.precision();} mainland.precision(_); galapagos.precision(_); return mercatorEcuador; }; mercatorEcuador.scale = function(_) { if (!arguments.length) {return mainland.scale();} mainland.scale(_); galapagos.scale(_); return mercatorEcuador.translate(mainland.translate()); }; mercatorEcuador.translate = function(_) { if (!arguments.length) {return mainland.translate();} var k = mainland.scale(), x = +_[0], y = +_[1]; /* var c0 = mainland(mainlandBbox[0]); var x0 = (x - c0[0]) / k; var y0 = (y - c0[1]) / k; var c1 = mainland(mainlandBbox[1]); var x1 = (x - c1[0]) / k; var y1 = (y - c1[1]) / k; console.info('mainland: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k]])'); c0 = galapagos.translate([x - 0.06 * k, y - 0.04 * k])(galapagosBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = galapagos.translate([x - 0.06 * k, y - 0.04 * k])(galapagosBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('galapagos: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])');*/ mainlandPoint = mainland .translate(_) .clipExtent([[x - 0.0262 * k, y - 0.0734 * k],[x + 0.1741 * k, y + 0.079 * k]]) .stream(pointStream); galapagosPoint = galapagos .translate([x - 0.06 * k, y - 0.04 * k]) .clipExtent([[x - 0.0857 * k + epsilon, y - 0.0676 * k + epsilon],[x - 0.0263 * k - epsilon, y - 0.026 * k - epsilon]]) .stream(pointStream); return mercatorEcuador; }; mercatorEcuador.drawCompositionBorders = function(context) { /* console.info("CLIP EXTENT: ", galapagos.clipExtent()); console.info("UL BBOX:", mainland.invert([galapagos.clipExtent()[0][0], galapagos.clipExtent()[0][1]])); console.info("UR BBOX:", mainland.invert([galapagos.clipExtent()[1][0], galapagos.clipExtent()[0][1]])); console.info("LD BBOX:", mainland.invert([galapagos.clipExtent()[1][0], galapagos.clipExtent()[1][1]])); console.info("LL BBOX:", mainland.invert([galapagos.clipExtent()[0][0], galapagos.clipExtent()[1][1]])); */ var ulgalapagos = mainland([-84.9032, 2.3757]); var urgalapagos = mainland([-81.5047, 2.3708]); var ldgalapagos = mainland([-81.5063, -0.01]); var llgalapagos = mainland([-84.9086, -0.005]); context.moveTo(ulgalapagos[0], ulgalapagos[1]); context.lineTo(urgalapagos[0], urgalapagos[1]); context.lineTo(ldgalapagos[0], ldgalapagos[1]); context.lineTo(llgalapagos[0], llgalapagos[1]); context.closePath(); }; mercatorEcuador.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return mercatorEcuador.scale(3500); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$5(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 Chile, configured by default for 960×500. function transverseMercatorChile() { var cache, cacheStream, mainland = d3Geo.geoTransverseMercator().rotate([72, 37]), mainlandPoint, antarctic = d3Geo.geoStereographic().rotate([72, 0]), antarcticPoint, juanFernandez = d3Geo.geoMercator().rotate([80, 33.5]), juanFernandezPoint, pascua = d3Geo.geoMercator().rotate([110, 25]), pascuaPoint, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var mainlandBbox = [[-75.5, -15.0], [-32, -49.0]]; var antarcticBbox = [[-91.0, -60.0], [-43.0, -90.0]]; var juanFernandezBbox = [[-81.0, -33.0], [-78.5, -34.0]]; var pascuaBbox = [[-110, -26.6], [-108.7, -27.5]]; */ function transverseMercatorChile(coordinates) { var x = coordinates[0], y = coordinates[1]; return point = null, (mainlandPoint.point(x, y), point) || (antarcticPoint.point(x, y), point) || (juanFernandezPoint.point(x, y), point) || (pascuaPoint.point(x, y), point); } transverseMercatorChile.invert = function(coordinates) { var k = mainland.scale(), t = mainland.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; /* //How are the return values calculated: console.info("******"); var c0 = antarctic(antarcticBbox[0]); var x0 = (c0[0] - t[0]) / k; var y0 = (c0[1] - t[1]) / k; console.info("p0 antarctic", x0 + ' - ' + y0); var c1 = antarctic(antarcticBbox[1]); var x1 = (c1[0] - t[0]) / k; var y1 = (c1[1] - t[1]) / k; console.info("p1 antarctic", x1 + ' - ' + y1); c0 = juanFernandez(juanFernandezBbox[0]); x0 = (c0[0] - t[0]) / k; y0 = (c0[1] - t[1]) / k; console.info("p0 juanFernandez", x0 + ' - ' + y0); c1 = juanFernandez(juanFernandezBbox[1]); x1 = (c1[0] - t[0]) / k; y1 = (c1[1] - t[1]) / k; console.info("p1 juanFernandez", x1 + ' - ' + y1); c0 = pascua(pascuaBbox[0]); x0 = (c0[0] - t[0]) / k; y0 = (c0[1] - t[1]) / k; console.info("p0 pascua", x0 + ' - ' + y0); c1 = pascua(pascuaBbox[1]); x1 = (c1[0] - t[0]) / k; y1 = (c1[1] - t[1]) / k; console.info("p1 pascua", x1 + ' - ' + y1); */ return (y >= 0.2582 && y< 0.32 && x >= -0.1036 && x < -0.087 ? antarctic : y >= -0.01298 && y< 0.0133 && x >= -0.11396 && x < -0.05944 ? juanFernandez : y >= 0.01539 && y< 0.03911 && x >= -0.089 && x < -0.0588 ? pascua : mainland).invert(coordinates); }; transverseMercatorChile.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$5([mainland.stream(cacheStream = stream), antarctic.stream(stream), juanFernandez.stream(stream), pascua.stream(stream)]); }; transverseMercatorChile.precision = function(_) { if (!arguments.length) {return mainland.precision();} mainland.precision(_); antarctic.precision(_); juanFernandez.precision(_); pascua.precision(_); return transverseMercatorChile; }; transverseMercatorChile.scale = function(_) { if (!arguments.length) {return mainland.scale();} mainland.scale(_); antarctic.scale(_ * 0.15); juanFernandez.scale(_ * 1.5); pascua.scale(_ * 1.5); return transverseMercatorChile.translate(mainland.translate()); }; transverseMercatorChile.translate = function(_) { if (!arguments.length) {return mainland.translate();} var k = mainland.scale(), x = +_[0], y = +_[1]; /* var c0 = mainland(mainlandBbox[0]); var x0 = (x - c0[0]) / k; var y0 = (y - c0[1]) / k; var c1 = mainland(mainlandBbox[1]); var x1 = (x - c1[0]) / k; var y1 = (y - c1[1]) / k; console.info('Mainland: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k]])'); c0 = antarctic.translate([x - 0.1 * k, y + 0.17 * k])(antarcticBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = antarctic.translate([x - 0.1 * k, y + 0.17 * k])(antarcticBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('antarctic: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('Doesn t work due to -90 latitude!' + '.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); c0 = juanFernandez.translate([x - 0.092 * k, y -0 * k])(juanFernandezBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = juanFernandez.translate([x - 0.092 * k, y -0 * k])(juanFernandezBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('juanFernandez: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); c0 = pascua.translate([x - 0.089 * k, y -0.0265 * k])(pascuaBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = pascua.translate([x - 0.089 * k, y -0.0265 * k])(pascuaBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('pascua: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); */ mainlandPoint = mainland .translate(_) .clipExtent([[x - 0.059 * k, y - 0.3835 * k],[x + 0.4498 * k, y + 0.3375 * k]]) .stream(pointStream); antarcticPoint = antarctic .translate([x - 0.087 * k, y + 0.17 * k]) .clipExtent([[x - 0.1166 * k + epsilon, y + 0.2582 * k + epsilon],[x - 0.06 * k - epsilon, y + 0.32 * k - epsilon]]) .stream(pointStream); juanFernandezPoint = juanFernandez .translate([x - 0.092 * k, y - 0 * k]) .clipExtent([[x - 0.114 * k + epsilon, y - 0.013 * k + epsilon],[x - 0.0594 * k - epsilon, y + 0.0133 * k - epsilon]]) .stream(pointStream); pascuaPoint = pascua .translate([x - 0.089 * k, y - 0.0265 * k]) .clipExtent([[x - 0.089 * k + epsilon, y + 0.0154 * k + epsilon],[x - 0.0588 * k - epsilon, y + 0.0391 * k - epsilon]]) .stream(pointStream); return transverseMercatorChile; }; transverseMercatorChile.drawCompositionBorders = function(context) { /* console.info("CLIP EXTENT antarctic: ", antarctic.clipExtent()); console.info("UL BBOX:", mainland.invert([antarctic.clipExtent()[0][0], antarctic.clipExtent()[0][1]])); console.info("UR BBOX:", mainland.invert([antarctic.clipExtent()[1][0], antarctic.clipExtent()[0][1]])); console.info("LD BBOX:", mainland.invert([antarctic.clipExtent()[1][0], antarctic.clipExtent()[1][1]])); console.info("LL BBOX:", mainland.invert([antarctic.clipExtent()[0][0], antarctic.clipExtent()[1][1]])); console.info("CLIP EXTENT juanFernandez: ", juanFernandez.clipExtent()); console.info("UL BBOX:", mainland.invert([juanFernandez.clipExtent()[0][0], juanFernandez.clipExtent()[0][1]])); console.info("UR BBOX:", mainland.invert([juanFernandez.clipExtent()[1][0], juanFernandez.clipExtent()[0][1]])); console.info("LD BBOX:", mainland.invert([juanFernandez.clipExtent()[1][0], juanFernandez.clipExtent()[1][1]])); console.info("LL BBOX:", mainland.invert([juanFernandez.clipExtent()[0][0], juanFernandez.clipExtent()[1][1]])); console.info("CLIP EXTENT pascua: ", pascua.clipExtent()); console.info("UL BBOX:", mainland.invert([pascua.clipExtent()[0][0], pascua.clipExtent()[0][1]])); console.info("UR BBOX:", mainland.invert([pascua.clipExtent()[1][0], pascua.clipExtent()[0][1]])); console.info("LD BBOX:", mainland.invert([pascua.clipExtent()[1][0], pascua.clipExtent()[1][1]])); console.info("LL BBOX:", mainland.invert([pascua.clipExtent()[0][0], pascua.clipExtent()[1][1]])); */ var ulantarctic = mainland([-82.6999, -51.3043]); var urantarctic = mainland([-77.5442, -51.6631]); var ldantarctic = mainland([-78.0254, -55.1860]); var llantarctic = mainland([-83.6106, -54.7785]); var uljuanFernandez = mainland([-80.0638, -35.9840]); var urjuanFernandez = mainland([-76.2153, -36.1811]); var ldjuanFernandez = mainland([-76.2994, -37.6839]); var lljuanFernandez = mainland([-80.2231, -37.4757]); var ulpascua = mainland([-78.442, -37.706]); var urpascua = mainland([-76.263, -37.8054]); var ldpascua = mainland([-76.344, -39.1595]); var llpascua = mainland([-78.5638, -39.0559]); context.moveTo(ulantarctic[0], ulantarctic[1]); context.lineTo(urantarctic[0], urantarctic[1]); context.lineTo(ldantarctic[0], ldantarctic[1]); context.lineTo(ldantarctic[0], ldantarctic[1]); context.lineTo(llantarctic[0], llantarctic[1]); context.closePath(); context.moveTo(uljuanFernandez[0], uljuanFernandez[1]); context.lineTo(urjuanFernandez[0], urjuanFernandez[1]); context.lineTo(ldjuanFernandez[0], ldjuanFernandez[1]); context.lineTo(ldjuanFernandez[0], ldjuanFernandez[1]); context.lineTo(lljuanFernandez[0], lljuanFernandez[1]); context.closePath(); context.moveTo(ulpascua[0], ulpascua[1]); context.lineTo(urpascua[0], urpascua[1]); context.lineTo(ldpascua[0], ldpascua[1]); context.lineTo(ldpascua[0], ldpascua[1]); context.lineTo(llpascua[0], llpascua[1]); context.closePath(); }; transverseMercatorChile.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return transverseMercatorChile.scale(700); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$6(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 Portugal, configured by default for 960×500. function conicEquidistantJapan() { var cache, cacheStream, mainland = d3Geo.geoConicEquidistant().rotate([-136, -22]).parallels([40, 34]), mainlandPoint, //gis.stackexchange.com/a/73135 hokkaido = d3Geo.geoConicEquidistant().rotate([-146, -26]).parallels([40, 34]), hokkaidoPoint, okinawa = d3Geo.geoConicEquidistant().rotate([-126, -19]).parallels([40, 34]), okinawaPoint, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var mainlandBbox = [[126.0, 41.606], [142.97, 29.97]]; var hokkaidoBbox = [[138.7, 45.61], [146.2, 41.2]]; var okinawaBbox = [[122.6, 29.0], [130, 23.7]]; */ function conicEquidistantJapan(coordinates) { var x = coordinates[0], y = coordinates[1]; return point = null, (mainlandPoint.point(x, y), point) || (hokkaidoPoint.point(x, y), point) || (okinawaPoint.point(x, y), point); } conicEquidistantJapan.invert = function(coordinates) { var k = mainland.scale(), t = mainland.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; /* //How are the return values calculated: console.info("******"); var c0 = hokkaido(hokkaidoBbox[0]); var x0 = (c0[0] - t[0]) / k; var y0 = (c0[1] - t[1]) / k; console.info("p0 hokkaido", x0 + ' - ' + y0); var c1 = hokkaido(hokkaidoBbox[1]); var x1 = (c1[0] - t[0]) / k; var y1 = (c1[1] - t[1]) / k; console.info("p1 hokkaido", x1 + ' - ' + y1); c0 = okinawa(okinawaBbox[0]); x0 = (c0[0] - t[0]) / k; y0 = (c0[1] - t[1]) / k; console.info("p0 okinawa", x0 + ' - ' + y0); c1 = okinawa(okinawaBbox[1]); x1 = (c1[0] - t[0]) / k; y1 = (c1[1] - t[1]) / k; console.info("p1 okinawa", x1 + ' - ' + y1); */ return (y >= -0.10925 && y< -0.02701 && x >= -0.135 && x < -0.0397 ? hokkaido : y >= 0.04713 && y< 0.11138 && x >= -0.03986 && x < 0.051 ? okinawa : mainland).invert(coordinates); }; conicEquidistantJapan.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$6([mainland.stream(cacheStream = stream), hokkaido.stream(stream), okinawa.stream(stream)]); }; conicEquidistantJapan.precision = function(_) { if (!arguments.length) {return mainland.precision();} mainland.precision(_); hokkaido.precision(_); okinawa.precision(_); return conicEquidistantJapan; }; conicEquidistantJapan.scale = function(_) { if (!arguments.length) {return mainland.scale();} mainland.scale(_); hokkaido.scale(_); okinawa.scale(_ * 0.7); return conicEquidistantJapan.translate(mainland.translate()); }; conicEquidistantJapan.translate = function(_) { if (!arguments.length) {return mainland.translate();} var k = mainland.scale(), x = +_[0], y = +_[1]; /* var c0 = mainland(mainlandBbox[0]); var x0 = (x - c0[0]) / k; var y0 = (y - c0[1]) / k; var c1 = mainland(mainlandBbox[1]); var x1 = (x - c1[0]) / k; var y1 = (y - c1[1]) / k; console.info('Main: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k]])'); c0 = hokkaido.translate([x - 0.0425 * k, y - 0.005 * k])(hokkaidoBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = hokkaido.translate([x - 0.0425 * k, y - 0.005 * k])(hokkaidoBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('hokkaido: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); c0 = okinawa.translate([x - 0 * k, y + 0 * k])(okinawaBbox[0]); x0 = (x - c0[0]) / k; y0 = (y - c0[1]) / k; c1 = okinawa.translate([x - 0 * k, y + 0 * k])(okinawaBbox[1]); x1 = (x - c1[0]) / k; y1 = (y - c1[1]) / k; console.info('okinawa: p0: ' + x0 + ', ' + y0 + ' , p1: ' + x1 + ' - ' + y1); console.info('.clipExtent([[x '+ (x0<0?'+ ':'- ') + Math.abs(x0.toFixed(4))+ ' * k + epsilon, y '+ (y0<0?'+ ':'- ') + Math.abs(y0.toFixed(4))+ ' * k + epsilon],[x '+ (x1<0?'+ ':'- ') + Math.abs(x1.toFixed(4))+ ' * k - epsilon, y '+ (y1<0?'+ ':'- ') + Math.abs(y1.toFixed(4))+ ' * k - epsilon]])'); */ mainlandPoint = mainland .translate(_) .clipExtent([[x - 0.1352 * k, y - 0.1091 * k],[x + 0.117 * k, y + 0.098 * k]]) .stream(pointStream); hokkaidoPoint = hokkaido .translate([x - 0.0425 * k, y - 0.005 * k]) .clipExtent([[x - 0.135 * k + epsilon, y - 0.1093 * k + epsilon],[x - 0.0397 * k - epsilon, y - 0.027 * k - epsilon]]) .stream(pointStream); okinawaPoint = okinawa .translate(_) .clipExtent([[x - 0.0399 * k + epsilon, y + 0.0471 * k + epsilon],[x + 0.051 * k - epsilon, y + 0.1114 * k - epsilon]]) .stream(pointStream); return conicEquidistantJapan; }; conicEquidistantJapan.drawCompositionBorders = function(context) { /* console.info("CLIP EXTENT hokkaido: ", hokkaido.clipExtent()); console.info("UL BBOX:", mainland.invert([hokkaido.clipExtent()[0][0], hokkaido.clipExtent()[0][1]])); console.info("UR BBOX:", mainland.invert([hokkaido.clipExtent()[1][0], hokkaido.clipExtent()[0][1]])); console.info("LD BBOX:", mainland.invert([hokkaido.clipExtent()[1][0], hokkaido.clipExtent()[1][1]])); console.info("LL BBOX:", mainland.invert([hokkaido.clipExtent()[0][0], hokkaido.clipExtent()[1][1]])); */ var ulhokkaido = mainland([ 126.01320483689143, 41.621090310215585 ]); var urhokkaido = mainland([ 133.04304387025903, 42.15087523707186 ]); var ldhokkaido = mainland([ 133.3021766080688, 37.43975444725098 ]); var llhokkaido = mainland([ 126.87889168628224, 36.95488945159779 ]); var llokinawa = mainland([132.9, 29.8]); var lmokinawa = mainland([134, 33]); var lrokinawa = mainland([139.3, 33.2]); var llrokinawa = mainland([139.16, 30.5]); context.moveTo(ulhokkaido[0], ulhokkaido[1]); context.lineTo(urhokkaido[0], urhokkaido[1]); context.lineTo(ldhokkaido[0], ldhokkaido[1]); context.lineTo(llhokkaido[0], llhokkaido[1]); context.closePath(); context.moveTo(llokinawa[0], llokinawa[1]); context.lineTo(lmokinawa[0], lmokinawa[1]); context.lineTo(lrokinawa[0], lrokinawa[1]); context.lineTo(llrokinawa[0], llrokinawa[1]); }; conicEquidistantJapan.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return conicEquidistantJapan.scale(2200); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$7(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 Portugal, configured by default for 960×500. function conicConformalFrance() { var cache, cacheStream, europe = d3Geo.geoConicConformal().rotate([-3, -46.2]).parallels([0, 60]), europePoint, guyane = d3Geo.geoMercator().center([-53.2, 3.9]), guyanePoint, martinique = d3Geo.geoMercator().center([-61.03, 14.67]), martiniquePoint, guadeloupe = d3Geo.geoMercator().center([-61.46, 16.14]), guadeloupePoint, saintBarthlemy = d3Geo.geoMercator().center([-62.85, 17.92]), saintBarthlemyPoint, stPierreMichelon = d3Geo.geoMercator().center([-56.23, 46.93]), stPierreMichelonPoint, mayotte = d3Geo.geoMercator().center([45.16, -12.8]), mayottePoint, reunion = d3Geo.geoMercator().center([55.52, -21.13]), reunionPoint, nouvelleCaledonie = d3Geo.geoMercator().center([165.8, -21.07]), nouvelleCaledoniePoint, wallisFutuna = d3Geo.geoMercator().center([-178.1, -14.3]), wallisFutunaPoint, polynesie = d3Geo.geoMercator().center([-150.55, -17.11]), polynesiePoint, polynesie2 = d3Geo.geoMercator().center([-150.55, -17.11]), polynesie2Point, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var europeBbox = [[-6.5, 51], [10, 41]]; var guyaneBbox = [[-54.5, 6.29], [-50.9, 1.48]]; */ function conicConformalFrance(coordinates) { var x = coordinates[0], y = coordinates[1]; return point = null, (europePoint.point(x, y), point) || (guyanePoint.point(x, y), point) || (martiniquePoint.point(x, y), point) || (guadeloupePoint.point(x, y), point) || (saintBarthlemyPoint.point(x, y), point) || (stPierreMichelonPoint.point(x, y), point) || (mayottePoint.point(x, y), point) || (reunionPoint.point(x, y), point) || (nouvelleCaledoniePoint.point(x, y), point) || (wallisFutunaPoint.point(x, y), point) || (polynesiePoint.point(x, y), point) || (polynesie2Point.point(x, y), point); } conicConformalFrance.invert = function(coordinates) { var k = europe.scale(), t = europe.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; return (y >= 0.029 && y< 0.0864 && x >= -0.14 && x < -0.0996 ? guyane : y >= 0 && y< 0.029 && x >= -0.14 && x < -0.0996 ? martinique : y >= -0.032 && y< 0 && x >= -0.14 && x < -0.0996 ? guadeloupe : y >= -0.052 && y< -0.032 && x >= -0.14 && x < -0.0996 ? saintBarthlemy : y >= -0.076 && y< 0.052 && x >= -0.14 && x < -0.0996 ? stPierreMichelon : y >= -0.076 && y< -0.052 && x >= 0.0967 && x < 0.1371 ? mayotte : y >= -0.052 && y< -0.02 && x >= 0.0967 && x < 0.1371 ? reunion : y >= -0.02 && y< 0.012 && x >= 0.0967 && x < 0.1371 ? nouvelleCaledonie : y >= 0.012 && y< 0.033 && x >= 0.0967 && x < 0.1371 ? wallisFutuna : y >= 0.033 && y< 0.0864 && x >= 0.0967 && x < 0.1371 ? polynesie : europe).invert(coordinates); }; conicConformalFrance.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$7([europe.stream(cacheStream = stream), guyane.stream(stream), martinique.stream(stream), guadeloupe.stream(stream), saintBarthlemy.stream(stream), stPierreMichelon.stream(stream), mayotte.stream(stream), reunion.stream(stream), nouvelleCaledonie.stream(stream), wallisFutuna.stream(stream), polynesie.stream(stream), polynesie2.stream(stream)]); }; conicConformalFrance.precision = function(_) { if (!arguments.length) {return europe.precision();} europe.precision(_); guyane.precision(_); martinique.precision(_); guadeloupe.precision(_); saintBarthlemy.precision(_); stPierreMichelon.precision(_); mayotte.precision(_); reunion.precision(_); nouvelleCaledonie.precision(_); wallisFutuna.precision(_); polynesie.precision(_); polynesie2.precision(_); return conicConformalFrance; }; conicConformalFrance.scale = function(_) { if (!arguments.length) {return europe.scale();} europe.scale(_); guyane.scale(_ * 0.6); martinique.scale(_ * 1.6); guadeloupe.scale(_ * 1.4); saintBarthlemy.scale(_ * 5); stPierreMichelon.scale(_ * 1.3); mayotte.scale(_ * 1.6); reunion.scale(_ * 1.2); nouvelleCaledonie.scale(_ * 0.3); wallisFutuna.scale(_ * 2.7); polynesie.scale(_ * 0.5); polynesie2.scale(_ * 0.06); return conicConformalFrance.translate(europe.translate()); }; conicConformalFrance.translate = function(_) { if (!arguments.length) {return europe.translate();} var k = europe.scale(), x = +_[0], y = +_[1]; europePoint = europe .translate(_) .clipExtent([[x - 0.0996 * k, y - 0.0908 * k],[x + 0.0967 * k, y + 0.0864 * k]]) .stream(pointStream); guyanePoint = guyane .translate([x - 0.12 * k, y + 0.0575 * k]) .clipExtent([[x - 0.14 * k + epsilon, y + 0.029 * k + epsilon],[x - 0.0996 * k - epsilon, y + 0.0864 * k - epsilon]]) .stream(pointStream); martiniquePoint = martinique .translate([x - 0.12 * k, y + 0.013 * k]) .clipExtent([[x - 0.14 * k + epsilon, y + 0 * k + epsilon],[x - 0.0996 * k - epsilon, y + 0.029 * k - epsilon]]) .stream(pointStream); guadeloupePoint = guadeloupe .translate([x - 0.12 * k, y -0.014 * k]) .clipExtent([[x - 0.14 * k + epsilon, y - 0.032 * k + epsilon],[x - 0.0996 * k - epsilon, y + 0 * k - epsilon]]) .stream(pointStream); saintBarthlemyPoint = saintBarthlemy .translate([x - 0.12 * k, y - 0.044 * k]) .clipExtent([[x - 0.14 * k + epsilon, y - 0.052 * k + epsilon],[x - 0.0996 * k - epsilon, y - 0.032 * k - epsilon]]) .stream(pointStream); stPierreMichelonPoint = stPierreMichelon .translate([x - 0.12 * k, y - 0.065 * k]) .clipExtent([[x - 0.14 * k + epsilon, y - 0.076 * k + epsilon],[x - 0.0996 * k - epsilon, y - 0.052 * k - epsilon]]) .stream(pointStream); mayottePoint = mayotte .translate([x + 0.117 * k, y - 0.064 * k]) .clipExtent([[x + 0.0967 * k + epsilon, y - 0.076 * k + epsilon],[x + 0.1371 * k - epsilon, y - 0.052 * k - epsilon]]) .stream(pointStream); reunionPoint = reunion .translate([x + 0.116 * k, y - 0.0355 * k]) .clipExtent([[x + 0.0967 * k + epsilon, y - 0.052 * k + epsilon],[x + 0.1371 * k - epsilon, y - 0.02 * k - epsilon]]) .stream(pointStream); nouvelleCaledoniePoint = nouvelleCaledonie .translate([x + 0.116 * k, y - 0.0048 * k]) .clipExtent([[x + 0.0967 * k + epsilon, y - 0.02 * k + epsilon],[x + 0.1371 * k - epsilon, y + 0.012 * k - epsilon]]) .stream(pointStream); wallisFutunaPoint = wallisFutuna .translate([x + 0.116 * k, y + 0.022 * k]) .clipExtent([[x + 0.0967 * k + epsilon, y + 0.012 * k + epsilon],[x + 0.1371 * k - epsilon, y + 0.033 * k - epsilon]]) .stream(pointStream); polynesie2Point = polynesie2 .translate([x + 0.11 * k, y + 0.045 * k]) .clipExtent([[x + 0.0967 * k + epsilon, y + 0.033 * k + epsilon],[x + 0.1371 * k - epsilon, y + 0.06 * k - epsilon]]) .stream(pointStream); polynesiePoint = polynesie .translate([x + 0.115 * k, y + 0.075 * k]) .clipExtent([[x + 0.0967 * k + epsilon, y + 0.06 * k + epsilon],[x + 0.1371 * k - epsilon, y + 0.0864 * k - epsilon]]) .stream(pointStream); return conicConformalFrance; }; conicConformalFrance.drawCompositionBorders = function(context) { /* console.log("var ul, ur, ld, ll;"); var projs = [guyane, martinique, guadeloupe, saintBarthlemy, stPierreMichelon, mayotte, reunion, nouvelleCaledonie, wallisFutuna, polynesie, polynesie2]; for (var i in projs){ var ul = europe.invert([projs[i].clipExtent()[0][0], projs[i].clipExtent()[0][1]]); var ur = europe.invert([projs[i].clipExtent()[1][0], projs[i].clipExtent()[0][1]]); var ld = europe.invert([projs[i].clipExtent()[1][0], projs[i].clipExtent()[1][1]]); var ll = europe.invert([projs[i].clipExtent()[0][0], projs[i].clipExtent()[1][1]]); console.log("ul = europe(["+ul+"]);"); console.log("ur = europe(["+ur+"]);"); console.log("ld = europe(["+ld+"]);"); console.log("ll = europe(["+ll+"]);"); console.log("context.moveTo(ul[0], ul[1]);"); console.log("context.lineTo(ur[0], ur[1]);"); console.log("context.lineTo(ld[0], ld[1]);"); console.log("context.lineTo(ll[0], ll[1]);"); console.log("context.closePath();"); }*/ var ul, ur, ld, ll; ul = europe([-7.938886725111036,43.7219460918835]); ur = europe([-4.832080896458295,44.12930268549372]); ld = europe([-4.205299743793263,40.98096346967365]); ll = europe([-7.071796453126152,40.610037319181444]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([-8.42751373617692,45.32889452553031]); ur = europe([-5.18599305777107,45.7566442062976]); ld = europe([-4.832080905154431,44.129302726751426]); ll = europe([-7.938886737126192,43.72194613263854]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([-9.012656899657046,47.127733821030176]); ur = europe([-5.6105244772793155,47.579777861410626]); ld = europe([-5.185993067168585,45.756644248170346]); ll = europe([-8.427513749141811,45.32889456686326]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([-9.405747558985553,48.26506375557457]); ur = europe([-5.896175018439575,48.733352850851624]); ld = europe([-5.610524487556043,47.57977790393761]); ll = europe([-9.012656913808351,47.127733862971255]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([-9.908436061346974,49.642448789505856]); ur = europe([-6.262026716233124,50.131426841787174]); ld = europe([-5.896175029331232,48.73335289377258]); ll = europe([-9.40574757396393,48.26506379787767]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([11.996907706504462,50.16039028163579]); ur = europe([15.649907879773343,49.68279246765253]); ld = europe([15.156712840526632,48.30371557625831]); ll = europe([11.64122661754411,48.761078240546816]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([11.641226606955788,48.7610781975889]); ur = europe([15.156712825832164,48.30371553390465]); ld = europe([14.549932166241172,46.4866532486199]); ll = europe([11.204443787952183,46.91899233914248]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([11.204443778297161,46.918992296823646]); ur = europe([14.549932152815039,46.486653206856396]); ld = europe([13.994409796764009,44.695833444323256]); ll = europe([10.805306599253848,45.105133870684924]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([10.805306590412085,45.10513382903308]); ur = europe([13.99440978444733,44.695833403183606]); ld = europe([13.654633799024392,43.53552468558152]); ll = europe([10.561516803980956,43.930671459798624]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([10.561516795617383,43.93067141859757]); ur = europe([13.654633787361952,43.5355246448671]); ld = europe([12.867691604239901,40.640701985019405]); ll = europe([9.997809515987688,41.00288343254471]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([10.8,42.4]); ur = europe([12.8,42.13]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); }; conicConformalFrance.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return conicConformalFrance.scale(2700); } // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. function multiplex$8(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 Portugal, configured by default for 960×500. function conicConformalEurope() { var cache, cacheStream, europe = d3Geo.geoConicConformal().rotate([-10, -53]).parallels([0, 60]), europePoint, guadeloupe = d3Geo.geoMercator().center([-61.46, 16.14]), guadeloupePoint, guyane = d3Geo.geoMercator().center([-53.2, 3.9]), guyanePoint, azores = d3Geo.geoConicConformal().rotate([27.8, -38.9]).parallels([0, 60]), azoresPoint, azores2 = d3Geo.geoConicConformal().rotate([25.43, -37.398]).parallels([0, 60]), azores2Point, azores3 = d3Geo.geoConicConformal().rotate([31.17, -39.539]).parallels([0, 60]), azores3Point, madeira = d3Geo.geoConicConformal().rotate([17, -32.7]).parallels([0, 60]), madeiraPoint, canaryIslands = d3Geo.geoConicConformal().rotate([16, -28.5]).parallels([0,60]), canaryIslandsPoint, martinique = d3Geo.geoMercator().center([-61.03, 14.67]), martiniquePoint, mayotte = d3Geo.geoMercator().center([45.16, -12.8]), mayottePoint, reunion = d3Geo.geoMercator().center([55.52, -21.13]), reunionPoint, malta = d3Geo.geoConicConformal().rotate([-14.4, -35.95]).parallels([0, 60]), maltaPoint, point, pointStream = {point: function(x, y) { point = [x, y]; }}; /* var europeBbox = [[-6.5, 51], [10, 41]]; var guyaneBbox = [[-54.5, 6.29], [-50.9, 1.48]]; */ function conicConformalEurope(coordinates) { var x = coordinates[0], y = coordinates[1]; return point = null, (europePoint.point(x, y), point) || (guyanePoint.point(x, y), point) || (martiniquePoint.point(x, y), point) || (guadeloupePoint.point(x, y), point) || (canaryIslandsPoint.point(x, y), point) || (madeiraPoint.point(x, y), point) || (mayottePoint.point(x, y), point) || (reunionPoint.point(x, y), point) || (maltaPoint.point(x, y), point) || (azoresPoint.point(x, y), point) || (azores2Point.point(x, y), point) || (azores3Point.point(x, y), point); } conicConformalEurope.invert = function(coordinates) { var k = europe.scale(), t = europe.translate(), x = (coordinates[0] - (t[0] + 0.08 * k)) / k, y = (coordinates[1] - t[1]) / k; return (y >= -0.31 && y< -0.24 && x >= 0.14 && x < 0.24 ? guadeloupe : y >= -0.24 && y< -0.17 && x >= 0.14 && x < 0.24 ? guyane : y >= -0.17 && y< -0.12 && x >= 0.21 && x < 0.24 ? azores2 : y >= -0.17 && y< -0.14 && x >= 0.14 && x < 0.165 ? azores3 : y >= -0.17 && y< -0.1 && x >= 0.14 && x < 0.24 ? azores : y >= -0.1 && y< -0.03 && x >= 0.14 && x < 0.24 ? madeira : y >= -0.03 && y< 0.04 && x >= 0.14 && x < 0.24 ? canaryIslands : y >= -0.31 && y< -0.24 && x >= 0.24 && x < 0.34 ? martinique : y >= -0.24 && y< -0.17 && x >= 0.24 && x < 0.34 ? mayotte : y >= -0.17 && y< -0.1 && x >= 0.24 && x < 0.34 ? reunion : y >= -0.1 && y< -0.03 && x >= 0.24 && x < 0.34 ? malta : europe).invert(coordinates); }; conicConformalEurope.stream = function(stream) { return cache && cacheStream === stream ? cache : cache = multiplex$8([europe.stream(cacheStream = stream), guyane.stream(stream), martinique.stream(stream), guadeloupe.stream(stream), canaryIslands.stream(stream), madeira.stream(stream), mayotte.stream(stream), reunion.stream(stream), malta.stream(stream), azores.stream(stream), azores2.stream(stream), azores3.stream(stream)]); }; conicConformalEurope.precision = function(_) { if (!arguments.length) {return europe.precision();} europe.precision(_); guyane.precision(_); martinique.precision(_); guadeloupe.precision(_); canaryIslands.precision(_); madeira.precision(_); mayotte.precision(_); reunion.precision(_); malta.precision(_); azores.precision(_); azores2.precision(_); azores3.precision(_); return conicConformalEurope; }; conicConformalEurope.scale = function(_) { if (!arguments.length) {return europe.scale();} europe.scale(_); guadeloupe.scale(_ * 3); guyane.scale(_ * 0.8); martinique.scale(_ * 3.5); reunion.scale(_ * 2.7); azores.scale(_ * 2); azores2.scale(_ * 2); azores3.scale(_ * 2); madeira.scale(_ * 3); canaryIslands.scale(_); mayotte.scale(_ * 5.5); malta.scale(_ * 6); return conicConformalEurope.translate(europe.translate()); }; conicConformalEurope.translate = function(_) { if (!arguments.length) {return europe.translate();} var k = europe.scale(), x = +_[0], y = +_[1]; europePoint = europe .translate([x - 0.08 * k, y]) .clipExtent([[x - 0.51 * k, y - 0.33 * k],[x + 0.5 * k, y + 0.33 * k]]) .stream(pointStream); guadeloupePoint = guadeloupe .translate([x + 0.19 * k, y - 0.275 * k]) .clipExtent([[x + 0.14 * k + epsilon, y - 0.31 * k + epsilon],[x + 0.24 * k - epsilon, y - 0.24 * k - epsilon]]) .stream(pointStream); guyanePoint = guyane .translate([x + 0.19 * k, y - 0.205 * k]) .clipExtent([[x + 0.14 * k + epsilon, y - 0.24 * k + epsilon],[x + 0.24 * k - epsilon, y - 0.17 * k - epsilon]]) .stream(pointStream); azoresPoint = azores .translate([x + 0.19 * k, y - 0.135 * k]) .clipExtent([[x + 0.14 * k + epsilon, y - 0.17 * k + epsilon],[x + 0.24 * k - epsilon, y - 0.1 * k - epsilon]]) .stream(pointStream); azores2Point = azores2 .translate([x + 0.225 * k, y - 0.147 * k]) .clipExtent([[x + 0.21 * k + epsilon, y - 0.17 * k + epsilon],[x + 0.24 * k - epsilon, y - 0.12 * k - epsilon]]) .stream(pointStream); azores3Point = azores3 .translate([x + 0.153 * k, y - 0.15 * k]) .clipExtent([[x + 0.14 * k + epsilon, y - 0.17 * k + epsilon],[x + 0.165 * k - epsilon, y - 0.14 * k - epsilon]]) .stream(pointStream); madeiraPoint = madeira .translate([x + 0.19 * k, y - 0.065 * k]) .clipExtent([[x + 0.14 * k + epsilon, y - 0.1 * k + epsilon],[x + 0.24 * k - epsilon, y - 0.03 * k - epsilon]]) .stream(pointStream); canaryIslandsPoint = canaryIslands .translate([x + 0.19 * k, y + 0.005 * k]) .clipExtent([[x + 0.14 * k + epsilon, y - 0.03 * k + epsilon],[x + 0.24 * k - epsilon, y + 0.04 * k - epsilon]]) .stream(pointStream); martiniquePoint = martinique .translate([x + 0.29 * k, y - 0.275 * k]) .clipExtent([[x + 0.24 * k + epsilon, y - 0.31 * k + epsilon],[x + 0.34 * k - epsilon, y - 0.24 * k - epsilon]]) .stream(pointStream); mayottePoint = mayotte .translate([x + 0.29 * k, y - 0.205 * k]) .clipExtent([[x + 0.24 * k + epsilon, y - 0.24 * k + epsilon],[x + 0.34 * k - epsilon, y - 0.17 * k - epsilon]]) .stream(pointStream); reunionPoint = reunion .translate([x + 0.29 * k, y - 0.135 * k]) .clipExtent([[x + 0.24 * k + epsilon, y - 0.17 * k + epsilon],[x + 0.34 * k - epsilon, y - 0.1 * k - epsilon]]) .stream(pointStream); maltaPoint = malta .translate([x + 0.29 * k, y - 0.065 * k]) .clipExtent([[x + 0.24 * k + epsilon, y - 0.1 * k + epsilon],[x + 0.34 * k - epsilon, y - 0.03 * k - epsilon]]) .stream(pointStream); return conicConformalEurope; }; conicConformalEurope.drawCompositionBorders = function(context) { /* console.log("var ul, ur, ld, ll;"); var projs = [guyane, martinique, guadeloupe, canaryIslands, madeira, mayotte, reunion, malta, azores, azores2, azores3]; for (var i in projs){ var ul = europe.invert([projs[i].clipExtent()[0][0], projs[i].clipExtent()[0][1]]); var ur = europe.invert([projs[i].clipExtent()[1][0], projs[i].clipExtent()[0][1]]); var ld = europe.invert([projs[i].clipExtent()[1][0], projs[i].clipExtent()[1][1]]); var ll = europe.invert([projs[i].clipExtent()[0][0], projs[i].clipExtent()[1][1]]); console.log("ul = europe(["+ul+"]);"); console.log("ur = europe(["+ur+"]);"); console.log("ld = europe(["+ld+"]);"); console.log("ll = europe(["+ll+"]);"); console.log("context.moveTo(ul[0], ul[1]);"); console.log("context.lineTo(ur[0], ur[1]);"); console.log("context.lineTo(ld[0], ld[1]);"); console.log("context.lineTo(ll[0], ll[1]);"); console.log("context.closePath();"); }*/ var ul, ur, ld, ll; ul = europe([42.45755610828648,63.343658547914934]); ur = europe([52.65837266667029,59.35045080290929]); ld = europe([47.19754502247785,56.12653496548117]); ll = europe([37.673034273363044,59.61638268506111]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([59.41110754003403,62.35069727399336]); ur = europe([66.75050228640794,57.11797303636038]); ld = europe([60.236065725110436,54.63331433818992]); ll = europe([52.65837313153311,59.350450804599355]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([48.81091130080243,66.93353402634641]); ur = europe([59.41110730654679,62.35069740653086]); ld = europe([52.6583728974441,59.3504509222445]); ll = europe([42.45755631675751,63.34365868805821]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([31.054198418446475,52.1080673766184]); ur = europe([39.09869284884117,49.400700047190554]); ld = europe([36.0580811499175,46.02944174908498]); ll = europe([28.690508588835726,48.433126979386415]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([33.977877745912025,55.849945501331]); ur = europe([42.75328432167726,52.78455122462353]); ld = europe([39.09869297540224,49.400700176148625]); ll = europe([31.05419851807008,52.10806751810923]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([52.658372900759296,59.35045068526415]); ur = europe([60.23606549583304,54.63331423800264]); ld = europe([54.6756370953122,51.892298789399455]); ll = europe([47.19754524788189,56.126534861222794]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([47.19754506082455,56.126534735591456]); ur = europe([54.675636900123514,51.892298681337095]); ld = europe([49.94448648951486,48.98775484983285]); ll = europe([42.75328468716108,52.78455126060818]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([42.75328453416769,52.78455113209101]); ur = europe([49.94448632339758,48.98775473706457]); ld = europe([45.912339990394315,45.99361784987003]); ll = europe([39.09869317356607,49.40070009378711]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([37.673034114296634,59.61638254183119]); ur = europe([47.197544835420544,56.126534839849846]); ld = europe([42.75328447467064,52.78455135314068]); ll = europe([33.977877870363905,55.849945644671145]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([44.56748486446032,57.26489367845818]); ld = europe([43.9335791193588,53.746540942601726]); ll = europe([43,56]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); ul = europe([37.673034114296634,59.61638254183119]); ur = europe([40.25902691953466,58.83002044222639]); ld = europe([38.458270492742024,57.26232178028002]); ll = europe([35.97754948030156,58.00266637992386]); context.moveTo(ul[0], ul[1]); context.lineTo(ur[0], ur[1]); context.lineTo(ld[0], ld[1]); context.lineTo(ll[0], ll[1]); context.closePath(); }; conicConformalEurope.getCompositionBorders = function() { var context = d3Path.path(); this.drawCompositionBorders(context); return context.toString(); }; return conicConformalEurope.scale(750); } exports.geoAlbersUsa = albersUsa; exports.geoAlbersUsaTerritories = albersUsaTerritories; exports.geoConicConformalSpain = conicConformalSpain; exports.geoConicConformalPortugal = conicConformalPortugal; exports.geoMercatorEcuador = mercatorEcuador; exports.geoTransverseMercatorChile = transverseMercatorChile; exports.geoConicEquidistantJapan = conicEquidistantJapan; exports.geoConicConformalFrance = conicConformalFrance; exports.geoConicConformalEurope = conicConformalEurope; Object.defineProperty(exports, '__esModule', { value: true }); })); },{"d3-geo":6,"d3-path":12}],6:[function(require,module,exports){ // https://d3js.org/d3-geo/ Version 1.2.4. Copyright 2016 Mike Bostock. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) : typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) : (factory((global.d3 = global.d3 || {}),global.d3)); }(this, (function (exports,d3Array) { 'use strict'; // 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/ function adder() { 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(temp, y, this.t); add(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(adder, a, b) { var x = adder.s = a + b, bv = x - a, av = x - bv; adder.t = (a - av) + (b - bv); } var epsilon = 1e-6; var epsilon2 = 1e-12; var pi = Math.PI; var halfPi = pi / 2; var quarterPi = pi / 4; var tau = pi * 2; var degrees = 180 / pi; var radians = pi / 180; var abs = Math.abs; var atan = Math.atan; var atan2 = Math.atan2; var cos = Math.cos; var ceil = Math.ceil; var exp = Math.exp; var log = Math.log; var pow = Math.pow; var sin = 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 : Math.acos(x); } function asin(x) { return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x); } function haversin(x) { return (x = sin(x / 2)) * x; } function noop() {} 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(); } function geoStream(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, lineStart: noop, lineEnd: noop, polygonStart: function() { areaRingSum.reset(); areaStream.lineStart = areaRingStart; areaStream.lineEnd = areaRingEnd; }, polygonEnd: function() { var areaRing = +areaRingSum; areaSum.add(areaRing < 0 ? tau + areaRing : areaRing); this.lineStart = this.lineEnd = this.point = noop; }, sphere: function() { areaSum.add(tau); } }; 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(phi = phi / 2 + quarterPi), sinPhi0 = sin(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(phi), sinPhi = sin(phi), k = sinPhi0 * sinPhi, u = cosPhi0 * cosPhi + k * cos(adLambda), v = k * sdLambda * sin(adLambda); areaRingSum.add(atan2(v, u)); // Advance the previous points. lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; } function area(object) { areaSum.reset(); geoStream(object, areaStream); return areaSum * 2; } function spherical(cartesian) { return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; } function cartesian(spherical) { var lambda = spherical[0], phi = spherical[1], cosPhi = cos(phi); return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(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(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) phi1 = 90; else if (deltaSum < -epsilon) 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 = delta > 0 ? 1 : -1, lambdai = inflection[0] * degrees * sign, phii, antimeridian = abs(delta) > 180; if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) { phii = inflection[1] * degrees; if (phii > phi1) phi1 = phii; } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) { phii = -inflection[1] * degrees; 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) 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; } function bounds(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, 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(phi); centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(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(phi); x0 = cosPhi * cos(lambda); y0 = cosPhi * sin(lambda); z0 = sin(phi); centroidStream.point = centroidLinePoint; centroidPointCartesian(x0, y0, z0); } function centroidLinePoint(lambda, phi) { lambda *= radians, phi *= radians; var cosPhi = cos(phi), x = cosPhi * cos(lambda), y = cosPhi * sin(lambda), z = sin(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 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(phi); x0 = cosPhi * cos(lambda); y0 = cosPhi * sin(lambda); z0 = sin(phi); centroidPointCartesian(x0, y0, z0); } function centroidRingPoint(lambda, phi) { lambda *= radians, phi *= radians; var cosPhi = cos(phi), x = cosPhi * cos(lambda), y = cosPhi * sin(lambda), z = sin(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); } function centroid(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) { x = X1, y = Y1, z = Z1; // If the feature has zero length, fall back to arithmetic mean of point vectors. if (W1 < epsilon) 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) return [NaN, NaN]; } return [atan2(y, x) * degrees, asin(z / sqrt(m)) * degrees]; } function constant(x) { return function() { return x; }; } function 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 rotationIdentity(lambda, phi) { return [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; } rotationIdentity.invert = rotationIdentity; function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { return (deltaLambda %= tau) ? (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 ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; }; } function rotationLambda(deltaLambda) { var rotation = forwardRotationLambda(deltaLambda); rotation.invert = forwardRotationLambda(-deltaLambda); return rotation; } function rotationPhiGamma(deltaPhi, deltaGamma) { var cosDeltaPhi = cos(deltaPhi), sinDeltaPhi = sin(deltaPhi), cosDeltaGamma = cos(deltaGamma), sinDeltaGamma = sin(deltaGamma); function rotation(lambda, phi) { var cosPhi = cos(phi), x = cos(lambda) * cosPhi, y = sin(lambda) * cosPhi, z = sin(phi), k = z * cosDeltaPhi + x * sinDeltaPhi; return [ atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), asin(k * cosDeltaGamma + y * sinDeltaGamma) ]; } rotation.invert = function(lambda, phi) { var cosPhi = cos(phi), x = cos(lambda) * cosPhi, y = sin(lambda) * cosPhi, z = sin(phi), k = z * cosDeltaGamma - y * sinDeltaGamma; return [ atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), asin(k * cosDeltaPhi - x * sinDeltaPhi) ]; }; return rotation; } function rotation(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, coordinates[1] *= degrees, coordinates; } forward.invert = function(coordinates) { coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); return coordinates[0] *= degrees, coordinates[1] *= degrees, 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(radius), sinRadius = sin(radius), step = direction * delta; if (t0 == null) { t0 = radius + direction * tau; t1 = radius - step / 2; } else { t0 = circleRadius(cosRadius, t0); t1 = circleRadius(cosRadius, t1); if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau; } for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(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 - epsilon) % tau; } function circle() { var center = constant([0, 0]), radius = constant(90), precision = constant(6), ring, rotate, stream = {point: point}; function point(x, y) { ring.push(x = rotate(x, y)); x[0] *= degrees, x[1] *= degrees; } 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([+_[0], +_[1]]), circle) : center; }; circle.radius = function(_) { return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius; }; circle.precision = function(_) { return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), circle) : precision; }; return circle; } function clipBuffer() { var lines = [], line; return { point: function(x, y) { line.push([x, y]); }, lineStart: function() { lines.push(line = []); }, lineEnd: noop, rejoin: function() { if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); }, result: function() { var result = lines; lines = []; line = null; return result; } }; } function clipLine(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; } function pointEqual(a, b) { return abs(a[0] - b[0]) < epsilon && abs(a[1] - b[1]) < epsilon; } 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. function clipPolygon(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(subject); link(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(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 ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < epsilon ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < epsilon ? 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 = d3Array.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; }; } function extent() { 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, point: noop, lineStart: lengthLineStart, lineEnd: noop, polygonStart: noop, polygonEnd: noop }; function lengthLineStart() { lengthStream.point = lengthPointFirst; lengthStream.lineEnd = lengthLineEnd; } function lengthLineEnd() { lengthStream.point = lengthStream.lineEnd = noop; } function lengthPointFirst(lambda, phi) { lambda *= radians, phi *= radians; lambda0$2 = lambda, sinPhi0$1 = sin(phi), cosPhi0$1 = cos(phi); lengthStream.point = lengthPoint; } function lengthPoint(lambda, phi) { lambda *= radians, phi *= radians; var sinPhi = sin(phi), cosPhi = cos(phi), delta = abs(lambda - lambda0$2), cosDelta = cos(delta), sinDelta = sin(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; } function length(object) { lengthSum.reset(); geoStream(object, lengthStream); return +lengthSum; } var coordinates = [null, null]; var object = {type: "LineString", coordinates: coordinates}; function distance(a, b) { coordinates[0] = a; coordinates[1] = b; return length(object); } function graticuleX(y0, y1, dy) { var y = d3Array.range(y0, y1 - epsilon, dy).concat(y1); return function(x) { return y.map(function(y) { return [x, y]; }); }; } function graticuleY(x0, x1, dx) { var x = d3Array.range(x0, x1 - epsilon, 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 d3Array.range(ceil(X0 / DX) * DX, X1, DX).map(X) .concat(d3Array.range(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) .concat(d3Array.range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon; }).map(x)) .concat(d3Array.range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon; }).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], [180, 90 - epsilon]]) .extentMinor([[-180, -80 - epsilon], [180, 80 + epsilon]]); } function interpolate(a, b) { var x0 = a[0] * radians, y0 = a[1] * radians, x1 = b[0] * radians, y1 = b[1] * radians, cy0 = cos(y0), sy0 = sin(y0), cy1 = cos(y1), sy1 = sin(y1), kx0 = cy0 * cos(x0), ky0 = cy0 * sin(x0), kx1 = cy1 * cos(x1), ky1 = cy1 * sin(x1), d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), k = sin(d); var interpolate = d ? function(t) { var B = sin(t *= d) / k, A = sin(d - t) / k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; return [ atan2(y, x) * degrees, atan2(z, sqrt(x * x + y * y)) * degrees ]; } : function() { return [x0 * degrees, y0 * degrees]; }; interpolate.distance = d; return interpolate; } function identity(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, lineStart: noop, lineEnd: noop, polygonStart: function() { areaStream$1.lineStart = areaRingStart$1; areaStream$1.lineEnd = areaRingEnd$1; }, polygonEnd: function() { areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop; 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, lineEnd: noop, polygonStart: noop, polygonEnd: noop, 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; } 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(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(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); break; } } }, result: noop }; function PathString() { this._string = []; } 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; } } }; 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"; } function index() { var pointRadius = 4.5, projection, projectionStream, context, 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 : _.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(null).context(null); } var sum = adder(); function polygonContains(polygon, point) { var lambda = point[0], phi = point[1], normal = [sin(lambda), -cos(lambda), 0], angle = 0, winding = 0; sum.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(phi0), cosPhi0 = cos(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(phi1), cosPhi1 = cos(phi1), delta = lambda1 - lambda0, sign = delta >= 0 ? 1 : -1, absDelta = sign * delta, antimeridian = absDelta > pi, k = sinPhi0 * sinPhi1; sum.add(atan2(k * sign * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta))); angle += antimeridian ? delta + sign * tau : 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(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 || angle < epsilon && sum < -epsilon) ^ (winding & 1); } function clip(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 = d3Array.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 - epsilon : halfPi - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon : halfPi - b[1]); } var clipAntimeridian = clip( function() { return true; }, clipAntimeridianLine, clipAntimeridianInterpolate, [-pi, -halfPi] ); // 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 : -pi, delta = abs(lambda1 - lambda0); if (abs(delta - pi) < epsilon) { // line crosses a pole stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi); stream.point(sign0, phi0); stream.lineEnd(); stream.lineStart(); stream.point(sign1, phi0); stream.point(lambda1, phi0); clean = 0; } else if (sign0 !== sign1 && delta >= pi) { // line crosses antimeridian if (abs(lambda0 - sign0) < epsilon) lambda0 -= sign0 * epsilon; // handle degeneracies if (abs(lambda1 - sign1) < epsilon) lambda1 -= sign1 * epsilon; 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(lambda0 - lambda1); return abs(sinLambda0Lambda1) > epsilon ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) : (phi0 + phi1) / 2; } function clipAntimeridianInterpolate(from, to, direction, stream) { var phi; if (from == null) { phi = direction * halfPi; stream.point(-pi, phi); stream.point(0, phi); stream.point(pi, phi); stream.point(pi, 0); stream.point(pi, -phi); stream.point(0, -phi); stream.point(-pi, -phi); stream.point(-pi, 0); stream.point(-pi, phi); } else if (abs(from[0] - to[0]) > epsilon) { var lambda = from[0] < to[0] ? pi : -pi; phi = direction * lambda / 2; stream.point(-lambda, phi); stream.point(0, phi); stream.point(lambda, phi); } else { stream.point(to[0], to[1]); } } function clipCircle(radius, delta) { var cr = cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > epsilon; // 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(lambda) * cos(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 : -pi), 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; point1[1] += epsilon; 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(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) < epsilon, meridian = polar || delta < epsilon; 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 ? phi0 : phi1) : phi0 <= q[1] && q[1] <= phi1 : delta > pi ^ (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 - 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, radius - pi]); } function transform(prototype) { return { stream: transform$1(prototype) }; } function transform$1(prototype) { function T() {} var p = T.prototype = Object.create(Transform.prototype); for (var k in prototype) p[k] = prototype[k]; return function(stream) { var t = new T; t.stream = stream; return t; }; } function Transform() {} Transform.prototype = { point: function(x, y) { this.stream.point(x, y); }, sphere: function() { this.stream.sphere(); }, lineStart: function() { this.stream.lineStart(); }, lineEnd: function() { this.stream.lineEnd(); }, polygonStart: function() { this.stream.polygonStart(); }, polygonEnd: function() { this.stream.polygonEnd(); } }; function fit(project, extent, object) { var w = extent[1][0] - extent[0][0], h = extent[1][1] - extent[0][1], clip = project.clipExtent && project.clipExtent(); project .scale(150) .translate([0, 0]); if (clip != null) project.clipExtent(null); geoStream(object, project.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) project.clipExtent(clip); return project .scale(k * 150) .translate([x, y]); } function fitSize(project) { return function(size, object) { return fit(project, [[0, 0], size], object); }; } function fitExtent(project) { return function(extent, object) { return fit(project, extent, object); }; } var maxDepth = 16; var cosMinDistance = cos(30 * radians); // cos(minimum angular distance) function resample(project, delta2) { return +delta2 ? resample$1(project, delta2) : resampleNone(project); } function resampleNone(project) { return transform$1({ 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(a * a + b * b + c * c), phi2 = asin(c /= m), lambda2 = abs(abs(c) - 1) < epsilon || abs(lambda0 - lambda1) < epsilon ? (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 = transform$1({ 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, // 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, point[1] * degrees]; } 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; }; projection.clipExtent = function(_) { return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : 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, phi * degrees]; }; projection.rotate = function(_) { return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees, deltaPhi * degrees, deltaGamma * degrees]; }; projection.precision = function(_) { return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); }; projection.fitExtent = fitExtent(projection); projection.fitSize = fitSize(projection); 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 / 3, m = projectionMutator(projectAt), p = m(phi0, phi1); p.parallels = function(_) { return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees, phi1 * degrees]; }; return p; } function conicEqualAreaRaw(y0, y1) { var sy0 = sin(y0), n = (sy0 + sin(y1)) / 2, c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; function project(x, y) { var r = sqrt(c - 2 * n * sin(y)) / n; return [r * sin(x *= n), r0 - r * cos(x)]; } project.invert = function(x, y) { var r0y = r0 - y; return [atan2(x, r0y) / n, asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; }; return project; } function conicEqualArea() { return conicProjection(conicEqualAreaRaw) .scale(155.424) .center([0, 33.6442]); } function albers() { 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 function albersUsa() { 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 albersUsa; }; 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, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]]) .stream(pointStream); hawaiiPoint = hawaii .translate([x - 0.205 * k, y + 0.212 * k]) .clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]]) .stream(pointStream); return albersUsa; }; albersUsa.fitExtent = fitExtent(albersUsa); albersUsa.fitSize = fitSize(albersUsa); return albersUsa.scale(1070); } function azimuthalRaw(scale) { return function(x, y) { var cx = cos(x), cy = cos(y), k = scale(cx * cy); return [ k * cy * sin(x), k * sin(y) ]; } } function azimuthalInvert(angle) { return function(x, y) { var z = sqrt(x * x + y * y), c = angle(z), sc = sin(c), cc = cos(c); return [ atan2(x * sc, z * cc), asin(z && y * sc / z) ]; } } var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { return sqrt(2 / (1 + cxcy)); }); azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { return 2 * asin(z / 2); }); function azimuthalEqualArea() { return projection(azimuthalEqualAreaRaw) .scale(124.75) .clipAngle(180 - 1e-3); } var azimuthalEquidistantRaw = azimuthalRaw(function(c) { return (c = acos(c)) && c / sin(c); }); azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { return z; }); function azimuthalEquidistant() { return projection(azimuthalEquidistantRaw) .scale(79.4188) .clipAngle(180 - 1e-3); } function mercatorRaw(lambda, phi) { return [lambda, log(tan((halfPi + phi) / 2))]; } mercatorRaw.invert = function(x, y) { return [x, 2 * atan(exp(y)) - halfPi]; }; function mercator() { return mercatorProjection(mercatorRaw) .scale(961 / tau); } 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 * 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 + y) / 2); } function conicConformalRaw(y0, y1) { var cy0 = cos(y0), n = y0 === y1 ? sin(y0) : log(cy0 / cos(y1)) / log(tany(y1) / tany(y0)), f = cy0 * pow(tany(y0), n) / n; if (!n) return mercatorRaw; function project(x, y) { if (f > 0) { if (y < -halfPi + epsilon) y = -halfPi + epsilon; } else { if (y > halfPi - epsilon) y = halfPi - epsilon; } var r = f / pow(tany(y), n); return [r * sin(n * x), f - r * cos(n * x)]; } project.invert = function(x, y) { var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy); return [atan2(x, fy) / n, 2 * atan(pow(f / r, 1 / n)) - halfPi]; }; return project; } function conicConformal() { return conicProjection(conicConformalRaw) .scale(109.5) .parallels([30, 30]); } function equirectangularRaw(lambda, phi) { return [lambda, phi]; } equirectangularRaw.invert = equirectangularRaw; function equirectangular() { return projection(equirectangularRaw) .scale(152.63); } function conicEquidistantRaw(y0, y1) { var cy0 = cos(y0), n = y0 === y1 ? sin(y0) : (cy0 - cos(y1)) / (y1 - y0), g = cy0 / n + y0; if (abs(n) < epsilon) return equirectangularRaw; function project(x, y) { var gy = g - y, nx = n * x; return [gy * sin(nx), g - gy * cos(nx)]; } project.invert = function(x, y) { var gy = g - y; return [atan2(x, gy) / n, g - sign(n) * sqrt(x * x + gy * gy)]; }; return project; } function conicEquidistant() { return conicProjection(conicEquidistantRaw) .scale(131.154) .center([0, 13.9389]); } function gnomonicRaw(x, y) { var cy = cos(y), k = cos(x) * cy; return [cy * sin(x) / k, sin(y) / k]; } gnomonicRaw.invert = azimuthalInvert(atan); function gnomonic() { return projection(gnomonicRaw) .scale(144.049) .clipAngle(60); } function orthographicRaw(x, y) { return [cos(y) * sin(x), sin(y)]; } orthographicRaw.invert = azimuthalInvert(asin); function orthographic() { return projection(orthographicRaw) .scale(249.5) .clipAngle(90 + epsilon); } function stereographicRaw(x, y) { var cy = cos(y), k = 1 + cos(x) * cy; return [cy * sin(x) / k, sin(y) / k]; } stereographicRaw.invert = azimuthalInvert(function(z) { return 2 * atan(z); }); function stereographic() { return projection(stereographicRaw) .scale(250) .clipAngle(142); } function transverseMercatorRaw(lambda, phi) { return [log(tan((halfPi + phi) / 2)), -lambda]; } transverseMercatorRaw.invert = function(x, y) { return [-y, 2 * atan(exp(x)) - halfPi]; }; function transverseMercator() { 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.geoArea = area; exports.geoBounds = bounds; exports.geoCentroid = centroid; exports.geoCircle = circle; exports.geoClipExtent = extent; exports.geoDistance = distance; exports.geoGraticule = graticule; exports.geoInterpolate = interpolate; exports.geoLength = length; exports.geoPath = index; 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.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; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{"d3-array":2}],7:[function(require,module,exports){ // https://d3js.org/d3-dispatch/ Version 1.0.1. 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 noop = {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(_[t], typename.name, callback); else if (callback == null) for (t in _) _[t] = set(_[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(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; } exports.dispatch = dispatch; Object.defineProperty(exports, '__esModule', { value: true }); })); },{}],8:[function(require,module,exports){ // https://d3js.org/d3-dsv/ Version 1.0.3. 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'; 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; } function dsv(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; 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; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{}],9:[function(require,module,exports){ // https://d3js.org/d3-ease/ Version 1.0.1. 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'; 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); 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; Object.defineProperty(exports, '__esModule', { value: true }); })); },{}],10:[function(require,module,exports){ // https://d3js.org/d3-geo/ Version 1.2.5. Copyright 2016 Mike Bostock. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) : typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) : (factory((global.d3 = global.d3 || {}),global.d3)); }(this, (function (exports,d3Array) { 'use strict'; // 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(temp, y, this.t); add(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(adder, a, b) { var x = adder.s = a + b, bv = x - a, av = x - bv; adder.t = (a - av) + (b - bv); } var epsilon = 1e-6; var epsilon2 = 1e-12; var pi = Math.PI; var halfPi = pi / 2; var quarterPi = pi / 4; var tau = pi * 2; var degrees = 180 / pi; var radians = pi / 180; var abs = Math.abs; var atan = Math.atan; var atan2 = Math.atan2; var cos = Math.cos; var ceil = Math.ceil; var exp = Math.exp; var log = Math.log; var pow = Math.pow; var sin = 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 : Math.acos(x); } function asin(x) { return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x); } function haversin(x) { return (x = sin(x / 2)) * x; } function noop() {} 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, lineStart: noop, lineEnd: noop, polygonStart: function() { areaRingSum.reset(); areaStream.lineStart = areaRingStart; areaStream.lineEnd = areaRingEnd; }, polygonEnd: function() { var areaRing = +areaRingSum; areaSum.add(areaRing < 0 ? tau + areaRing : areaRing); this.lineStart = this.lineEnd = this.point = noop; }, sphere: function() { areaSum.add(tau); } }; 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(phi = phi / 2 + quarterPi), sinPhi0 = sin(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(phi), sinPhi = sin(phi), k = sinPhi0 * sinPhi, u = cosPhi0 * cosPhi + k * cos(adLambda), v = k * sdLambda * sin(adLambda); areaRingSum.add(atan2(v, u)); // Advance the previous points. lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; } var area = function(object) { areaSum.reset(); geoStream(object, areaStream); return areaSum * 2; } function spherical(cartesian) { return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; } function cartesian(spherical) { var lambda = spherical[0], phi = spherical[1], cosPhi = cos(phi); return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(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(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) phi1 = 90; else if (deltaSum < -epsilon) 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 * sign$$1, phii, antimeridian = abs(delta) > 180; if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { phii = inflection[1] * degrees; 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; 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) 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$$1, x) { return range$$1[0] <= range$$1[1] ? range$$1[0] <= x && x <= range$$1[1] : x < range$$1[0] || range$$1[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, 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(phi); centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(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(phi); x0 = cosPhi * cos(lambda); y0 = cosPhi * sin(lambda); z0 = sin(phi); centroidStream.point = centroidLinePoint; centroidPointCartesian(x0, y0, z0); } function centroidLinePoint(lambda, phi) { lambda *= radians, phi *= radians; var cosPhi = cos(phi), x = cosPhi * cos(lambda), y = cosPhi * sin(lambda), z = sin(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 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(phi); x0 = cosPhi * cos(lambda); y0 = cosPhi * sin(lambda); z0 = sin(phi); centroidPointCartesian(x0, y0, z0); } function centroidRingPoint(lambda, phi) { lambda *= radians, phi *= radians; var cosPhi = cos(phi), x = cosPhi * cos(lambda), y = cosPhi * sin(lambda), z = sin(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); } 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) { x = X1, y = Y1, z = Z1; // If the feature has zero length, fall back to arithmetic mean of point vectors. if (W1 < epsilon) 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) return [NaN, NaN]; } return [atan2(y, x) * degrees, asin(z / sqrt(m)) * degrees]; } var constant = 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 ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; } rotationIdentity.invert = rotationIdentity; function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { return (deltaLambda %= tau) ? (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 ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; }; } function rotationLambda(deltaLambda) { var rotation = forwardRotationLambda(deltaLambda); rotation.invert = forwardRotationLambda(-deltaLambda); return rotation; } function rotationPhiGamma(deltaPhi, deltaGamma) { var cosDeltaPhi = cos(deltaPhi), sinDeltaPhi = sin(deltaPhi), cosDeltaGamma = cos(deltaGamma), sinDeltaGamma = sin(deltaGamma); function rotation(lambda, phi) { var cosPhi = cos(phi), x = cos(lambda) * cosPhi, y = sin(lambda) * cosPhi, z = sin(phi), k = z * cosDeltaPhi + x * sinDeltaPhi; return [ atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), asin(k * cosDeltaGamma + y * sinDeltaGamma) ]; } rotation.invert = function(lambda, phi) { var cosPhi = cos(phi), x = cos(lambda) * cosPhi, y = sin(lambda) * cosPhi, z = sin(phi), k = z * cosDeltaGamma - y * sinDeltaGamma; return [ atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), asin(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, coordinates[1] *= degrees, coordinates; } forward.invert = function(coordinates) { coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); return coordinates[0] *= degrees, coordinates[1] *= degrees, 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(radius), sinRadius = sin(radius), step = direction * delta; if (t0 == null) { t0 = radius + direction * tau; t1 = radius - step / 2; } else { t0 = circleRadius(cosRadius, t0); t1 = circleRadius(cosRadius, t1); if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau; } for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(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 - epsilon) % tau; } var circle = function() { var center = constant([0, 0]), radius = constant(90), precision = constant(6), ring, rotate, stream = {point: point}; function point(x, y) { ring.push(x = rotate(x, y)); x[0] *= degrees, x[1] *= degrees; } 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([+_[0], +_[1]]), circle) : center; }; circle.radius = function(_) { return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius; }; circle.precision = function(_) { return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), 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, 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 && abs(a[1] - b[1]) < epsilon; } 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(subject); link(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(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 ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < epsilon ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < epsilon ? 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 = d3Array.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 = 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, point: noop, lineStart: lengthLineStart, lineEnd: noop, polygonStart: noop, polygonEnd: noop }; function lengthLineStart() { lengthStream.point = lengthPointFirst; lengthStream.lineEnd = lengthLineEnd; } function lengthLineEnd() { lengthStream.point = lengthStream.lineEnd = noop; } function lengthPointFirst(lambda, phi) { lambda *= radians, phi *= radians; lambda0$2 = lambda, sinPhi0$1 = sin(phi), cosPhi0$1 = cos(phi); lengthStream.point = lengthPoint; } function lengthPoint(lambda, phi) { lambda *= radians, phi *= radians; var sinPhi = sin(phi), cosPhi = cos(phi), delta = abs(lambda - lambda0$2), cosDelta = cos(delta), sinDelta = sin(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 length = function(object) { lengthSum.reset(); geoStream(object, lengthStream); return +lengthSum; } var coordinates = [null, null]; var object = {type: "LineString", coordinates: coordinates}; var distance = function(a, b) { coordinates[0] = a; coordinates[1] = b; return length(object); } function graticuleX(y0, y1, dy) { var y = d3Array.range(y0, y1 - epsilon, dy).concat(y1); return function(x) { return y.map(function(y) { return [x, y]; }); }; } function graticuleY(x0, x1, dx) { var x = d3Array.range(x0, x1 - epsilon, dx).concat(x1); return function(y) { return x.map(function(x) { return [x, y]; }); }; } var graticule = function() { var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; function graticule() { return {type: "MultiLineString", coordinates: lines()}; } function lines() { return d3Array.range(ceil(X0 / DX) * DX, X1, DX).map(X) .concat(d3Array.range(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) .concat(d3Array.range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon; }).map(x)) .concat(d3Array.range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon; }).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], [180, 90 - epsilon]]) .extentMinor([[-180, -80 - epsilon], [180, 80 + epsilon]]); } var interpolate = function(a, b) { var x0 = a[0] * radians, y0 = a[1] * radians, x1 = b[0] * radians, y1 = b[1] * radians, cy0 = cos(y0), sy0 = sin(y0), cy1 = cos(y1), sy1 = sin(y1), kx0 = cy0 * cos(x0), ky0 = cy0 * sin(x0), kx1 = cy1 * cos(x1), ky1 = cy1 * sin(x1), d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), k = sin(d); var interpolate = d ? function(t) { var B = sin(t *= d) / k, A = sin(d - t) / k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; return [ atan2(y, x) * degrees, atan2(z, sqrt(x * x + y * y)) * degrees ]; } : function() { return [x0 * degrees, y0 * degrees]; }; interpolate.distance = d; return interpolate; } var identity = 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, lineStart: noop, lineEnd: noop, polygonStart: function() { areaStream$1.lineStart = areaRingStart$1; areaStream$1.lineEnd = areaRingEnd$1; }, polygonEnd: function() { areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop; 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, lineEnd: noop, polygonStart: noop, polygonEnd: noop, 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(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(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); break; } } }, result: noop }; function PathString() { this._string = []; } 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; } } }; 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"; } var index = function() { var pointRadius = 4.5, projection, projectionStream, context, 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 : _.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(null).context(null); } var sum = adder(); var polygonContains = function(polygon, point) { var lambda = point[0], phi = point[1], normal = [sin(lambda), -cos(lambda), 0], angle = 0, winding = 0; sum.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(phi0), cosPhi0 = cos(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(phi1), cosPhi1 = cos(phi1), delta = lambda1 - lambda0, sign$$1 = delta >= 0 ? 1 : -1, absDelta = sign$$1 * delta, antimeridian = absDelta > pi, k = sinPhi0 * sinPhi1; sum.add(atan2(k * sign$$1 * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta))); angle += antimeridian ? delta + sign$$1 * tau : 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(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 || angle < epsilon && sum < -epsilon) ^ (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 = d3Array.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 - epsilon : halfPi - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon : halfPi - b[1]); } var clipAntimeridian = clip( function() { return true; }, clipAntimeridianLine, clipAntimeridianInterpolate, [-pi, -halfPi] ); // 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 : -pi, delta = abs(lambda1 - lambda0); if (abs(delta - pi) < epsilon) { // line crosses a pole stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi); stream.point(sign0, phi0); stream.lineEnd(); stream.lineStart(); stream.point(sign1, phi0); stream.point(lambda1, phi0); clean = 0; } else if (sign0 !== sign1 && delta >= pi) { // line crosses antimeridian if (abs(lambda0 - sign0) < epsilon) lambda0 -= sign0 * epsilon; // handle degeneracies if (abs(lambda1 - sign1) < epsilon) lambda1 -= sign1 * epsilon; 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(lambda0 - lambda1); return abs(sinLambda0Lambda1) > epsilon ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) : (phi0 + phi1) / 2; } function clipAntimeridianInterpolate(from, to, direction, stream) { var phi; if (from == null) { phi = direction * halfPi; stream.point(-pi, phi); stream.point(0, phi); stream.point(pi, phi); stream.point(pi, 0); stream.point(pi, -phi); stream.point(0, -phi); stream.point(-pi, -phi); stream.point(-pi, 0); stream.point(-pi, phi); } else if (abs(from[0] - to[0]) > epsilon) { var lambda = from[0] < to[0] ? pi : -pi; 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(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > epsilon; // 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(lambda) * cos(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 : -pi), 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; point1[1] += epsilon; 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(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) < epsilon, meridian = polar || delta < epsilon; 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 ? phi0 : phi1) : phi0 <= q[1] && q[1] <= phi1 : delta > pi ^ (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 - 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, radius - pi]); } var transform = function(prototype) { return { stream: transform$1(prototype) }; } function transform$1(prototype) { function T() {} var p = T.prototype = Object.create(Transform.prototype); for (var k in prototype) p[k] = prototype[k]; return function(stream) { var t = new T; t.stream = stream; return t; }; } function Transform() {} Transform.prototype = { point: function(x, y) { this.stream.point(x, y); }, sphere: function() { this.stream.sphere(); }, lineStart: function() { this.stream.lineStart(); }, lineEnd: function() { this.stream.lineEnd(); }, polygonStart: function() { this.stream.polygonStart(); }, polygonEnd: function() { this.stream.polygonEnd(); } }; function fit(project, extent, object) { var w = extent[1][0] - extent[0][0], h = extent[1][1] - extent[0][1], clip = project.clipExtent && project.clipExtent(); project .scale(150) .translate([0, 0]); if (clip != null) project.clipExtent(null); geoStream(object, project.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) project.clipExtent(clip); return project .scale(k * 150) .translate([x, y]); } function fitSize(project) { return function(size, object) { return fit(project, [[0, 0], size], object); }; } function fitExtent(project) { return function(extent, object) { return fit(project, extent, object); }; } var maxDepth = 16; var cosMinDistance = cos(30 * radians); // cos(minimum angular distance) var resample = function(project, delta2) { return +delta2 ? resample$1(project, delta2) : resampleNone(project); } function resampleNone(project) { return transform$1({ 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(a * a + b * b + c * c), phi2 = asin(c /= m), lambda2 = abs(abs(c) - 1) < epsilon || abs(lambda0 - lambda1) < epsilon ? (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 = transform$1({ 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, // 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, point[1] * degrees]; } 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; }; projection.clipExtent = function(_) { return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : 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, phi * degrees]; }; projection.rotate = function(_) { return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees, deltaPhi * degrees, deltaGamma * degrees]; }; projection.precision = function(_) { return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); }; projection.fitExtent = fitExtent(projection); projection.fitSize = fitSize(projection); 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 / 3, m = projectionMutator(projectAt), p = m(phi0, phi1); p.parallels = function(_) { return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees, phi1 * degrees]; }; return p; } function conicEqualAreaRaw(y0, y1) { var sy0 = sin(y0), n = (sy0 + sin(y1)) / 2, c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; function project(x, y) { var r = sqrt(c - 2 * n * sin(y)) / n; return [r * sin(x *= n), r0 - r * cos(x)]; } project.invert = function(x, y) { var r0y = r0 - y; return [atan2(x, r0y) / n, 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 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, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]]) .stream(pointStream); hawaiiPoint = hawaii .translate([x - 0.205 * k, y + 0.212 * k]) .clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]]) .stream(pointStream); return reset(); }; albersUsa.fitExtent = fitExtent(albersUsa); albersUsa.fitSize = fitSize(albersUsa); function reset() { cache = cacheStream = null; return albersUsa; } return albersUsa.scale(1070); } function azimuthalRaw(scale) { return function(x, y) { var cx = cos(x), cy = cos(y), k = scale(cx * cy); return [ k * cy * sin(x), k * sin(y) ]; } } function azimuthalInvert(angle) { return function(x, y) { var z = sqrt(x * x + y * y), c = angle(z), sc = sin(c), cc = cos(c); return [ atan2(x * sc, z * cc), asin(z && y * sc / z) ]; } } var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { return sqrt(2 / (1 + cxcy)); }); azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { return 2 * asin(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(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(tan((halfPi + phi) / 2))]; } mercatorRaw.invert = function(x, y) { return [x, 2 * atan(exp(y)) - halfPi]; }; var mercator = function() { return mercatorProjection(mercatorRaw) .scale(961 / tau); } 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 * 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 + y) / 2); } function conicConformalRaw(y0, y1) { var cy0 = cos(y0), n = y0 === y1 ? sin(y0) : log(cy0 / cos(y1)) / log(tany(y1) / tany(y0)), f = cy0 * pow(tany(y0), n) / n; if (!n) return mercatorRaw; function project(x, y) { if (f > 0) { if (y < -halfPi + epsilon) y = -halfPi + epsilon; } else { if (y > halfPi - epsilon) y = halfPi - epsilon; } var r = f / pow(tany(y), n); return [r * sin(n * x), f - r * cos(n * x)]; } project.invert = function(x, y) { var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy); return [atan2(x, fy) / n, 2 * atan(pow(f / r, 1 / n)) - halfPi]; }; 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(y0), n = y0 === y1 ? sin(y0) : (cy0 - cos(y1)) / (y1 - y0), g = cy0 / n + y0; if (abs(n) < epsilon) return equirectangularRaw; function project(x, y) { var gy = g - y, nx = n * x; return [gy * sin(nx), g - gy * cos(nx)]; } project.invert = function(x, y) { var gy = g - y; return [atan2(x, gy) / n, g - sign(n) * sqrt(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(y), k = cos(x) * cy; return [cy * sin(x) / k, sin(y) / k]; } gnomonicRaw.invert = azimuthalInvert(atan); var gnomonic = function() { return projection(gnomonicRaw) .scale(144.049) .clipAngle(60); } function orthographicRaw(x, y) { return [cos(y) * sin(x), sin(y)]; } orthographicRaw.invert = azimuthalInvert(asin); var orthographic = function() { return projection(orthographicRaw) .scale(249.5) .clipAngle(90 + epsilon); } function stereographicRaw(x, y) { var cy = cos(y), k = 1 + cos(x) * cy; return [cy * sin(x) / k, sin(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(tan((halfPi + phi) / 2)), -lambda]; } transverseMercatorRaw.invert = function(x, y) { return [-y, 2 * atan(exp(x)) - halfPi]; }; 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.geoArea = area; exports.geoBounds = bounds; exports.geoCentroid = centroid; exports.geoCircle = circle; exports.geoClipExtent = extent; exports.geoDistance = distance; exports.geoGraticule = graticule; exports.geoInterpolate = interpolate; exports.geoLength = length; exports.geoPath = index; 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.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; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{"d3-array":2}],11:[function(require,module,exports){ // https://d3js.org/d3-interpolate/ Version 1.1.1. Copyright 2016 Mike Bostock. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-color')) : typeof define === 'function' && define.amd ? define(['exports', 'd3-color'], factory) : (factory((global.d3 = global.d3 || {}),global.d3)); }(this, function (exports,d3Color) { 'use strict'; 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; } function basis$1(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 basisClosed(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); }; } function constant(x) { return function() { return x; }; } function linear(a, d) { return function(t) { return a + t * d; }; } 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 hue(a, b) { var d = b - a; return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a); } function gamma(y) { return (y = +y) === 1 ? nogamma : function(a, b) { return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a); }; } function nogamma(a, b) { var d = b - a; return d ? linear(a, d) : constant(isNaN(a) ? b : a); } var rgb$1 = (function rgbGamma(y) { var color = gamma(y); function rgb(start, end) { var r = color((start = d3Color.rgb(start)).r, (end = d3Color.rgb(end)).r), g = color(start.g, end.g), b = color(start.b, end.b), opacity = color(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.gamma = rgbGamma; return rgb; })(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; for (i = 0; i < n; ++i) { color = d3Color.rgb(colors[i]); r[i] = color.r || 0; g[i] = color.g || 0; b[i] = color.b || 0; } r = spline(r); g = spline(g); b = spline(b); color.opacity = 1; return function(t) { color.r = r(t); color.g = g(t); color.b = b(t); return color + ""; }; }; } var rgbBasis = rgbSpline(basis$1); var rgbBasisClosed = rgbSpline(basisClosed); function array(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] = value(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; }; } function date(a, b) { var d = new Date; return a = +a, b -= a, function(t) { return d.setTime(a + b * t), d; }; } function number(a, b) { return a = +a, b -= a, function(t) { return a + b * t; }; } function object(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] = value(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) + ""; }; } function string(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: number(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(""); }); } function value(a, b) { var t = typeof b, c; return b == null || t === "boolean" ? constant(b) : (t === "number" ? number : t === "string" ? ((c = d3Color.color(b)) ? (b = c, rgb$1) : string) : b instanceof d3Color.color ? rgb$1 : b instanceof Date ? date : Array.isArray(b) ? array : isNaN(b) ? object : number)(a, b); } function round(a, b) { return a = +a, b -= a, function(t) { return Math.round(a + b * t); }; } var degrees = 180 / Math.PI; var identity = { translateX: 0, translateY: 0, rotate: 0, skewX: 0, scaleX: 1, scaleY: 1 }; function decompose(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; 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; if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); svgNode.setAttribute("transform", value); if (!(value = svgNode.transform.baseVal.consolidate())) return identity; 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: number(xa, xb)}, {i: i - 2, x: number(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: number(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: number(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: number(xa, xb)}, {i: i - 2, x: number(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] function zoom(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) { return function(start, end) { var h = hue((start = d3Color.hsl(start)).h, (end = d3Color.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 = d3Color.lab(start)).l, (end = d3Color.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) { return function(start, end) { var h = hue((start = d3Color.hcl(start)).h, (end = d3Color.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) { return (function cubehelixGamma(y) { y = +y; function cubehelix(start, end) { var h = hue((start = d3Color.cubehelix(start)).h, (end = d3Color.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.gamma = cubehelixGamma; return cubehelix; })(1); } var cubehelix$2 = cubehelix$1(hue); var cubehelixLong = cubehelix$1(nogamma); function quantize(interpolator, n) { var samples = new Array(n); for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); return samples; } exports.interpolate = value; exports.interpolateArray = array; exports.interpolateBasis = basis$1; exports.interpolateBasisClosed = basisClosed; exports.interpolateDate = date; exports.interpolateNumber = number; exports.interpolateObject = object; exports.interpolateRound = round; exports.interpolateString = string; exports.interpolateTransformCss = interpolateTransformCss; exports.interpolateTransformSvg = interpolateTransformSvg; exports.interpolateZoom = zoom; exports.interpolateRgb = rgb$1; 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; Object.defineProperty(exports, '__esModule', { value: true }); })); },{"d3-color":4}],12:[function(require,module,exports){ // https://d3js.org/d3-path/ Version 1.0.2. 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 pi = Math.PI; var tau = 2 * pi; var epsilon = 1e-6; var tauEpsilon = tau - 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 - 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 + tau; this._.push( "A", r, ",", r, ",0,", +(da >= pi), ",", 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(""); } }; exports.path = path; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{}],13:[function(require,module,exports){ // https://d3js.org/d3-request/ Version 1.0.2. Copyright 2016 Mike Bostock. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-collection'), require('d3-dispatch'), require('d3-dsv')) : typeof define === 'function' && define.amd ? define(['exports', 'd3-collection', 'd3-dispatch', 'd3-dsv'], factory) : (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3)); }(this, function (exports,d3Collection,d3Dispatch,d3Dsv) { 'use strict'; function request(url, callback) { var request, event = d3Dispatch.dispatch("beforesend", "progress", "load", "error"), mimeType, headers = d3Collection.map(), 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 } function type(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; }); function dsv(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) { return parse(request.responseText, row); }; } var csv = dsv("text/csv", d3Dsv.csvParse); var tsv = dsv("text/tab-separated-values", d3Dsv.tsvParse); exports.request = request; exports.html = html; exports.json = json; exports.text = text; exports.xml = xml; exports.csv = csv; exports.tsv = tsv; Object.defineProperty(exports, '__esModule', { value: true }); })); },{"d3-collection":3,"d3-dispatch":7,"d3-dsv":8}],14:[function(require,module,exports){ // https://d3js.org/d3-selection/ Version 1.0.2. 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 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/" }; function namespace(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); }; } function creator(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(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); }; } function selection_on(typename, value, capture) { var typenames = parseTypenames(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; } } function sourceEvent() { var current = exports.event, source; while (source = current.sourceEvent) current = source; return current; } function point(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]; } function mouse(node) { var event = sourceEvent(); if (event.changedTouches) event = event.changedTouches[0]; return point(node, event); } function none() {} function selector(selector) { return selector == null ? none : function() { return this.querySelector(selector); }; } function selection_select(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 []; } function selectorAll(selector) { return selector == null ? empty : function() { return this.querySelectorAll(selector); }; } function selection_selectAll(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); } function selection_filter(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); } function sparse(update) { return new Array(update.length); } function selection_enter() { 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); } }; function constant(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; } } } function selection_data(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(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; } function selection_exit() { return new Selection(this._exit || this._groups.map(sparse), this._parents); } function selection_merge(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); } function selection_order() { 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; } function selection_sort(compare) { if (!compare) compare = ascending; 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(a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; } function selection_call() { var callback = arguments[0]; arguments[0] = this; callback.apply(null, arguments); return this; } function selection_nodes() { var nodes = new Array(this.size()), i = -1; this.each(function() { nodes[++i] = this; }); return nodes; } function selection_node() { 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; } function selection_size() { var size = 0; this.each(function() { ++size; }); return size; } function selection_empty() { return !this.node(); } function selection_each(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); }; } function selection_attr(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)); } function defaultView(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); }; } function selection_style(name, value, priority) { var node; return arguments.length > 1 ? this.each((value == null ? styleRemove : typeof value === "function" ? styleFunction : styleConstant)(name, value, priority == null ? "" : priority)) : defaultView(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; }; } function selection_property(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); }; } function selection_classed(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; }; } function selection_text(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; }; } function selection_html(value) { return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML; } function raise() { if (this.nextSibling) this.parentNode.appendChild(this); } function selection_raise() { return this.each(raise); } function lower() { if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); } function selection_lower() { return this.each(lower); } function selection_append(name) { var create = typeof name === "function" ? name : creator(name); return this.select(function() { return this.appendChild(create.apply(this, arguments)); }); } function constantNull() { return null; } function selection_insert(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); } function selection_remove() { return this.each(remove); } function selection_datum(value) { return arguments.length ? this.property("__data__", value) : this.node().__data__; } function dispatchEvent(node, type, params) { var window = defaultView(node), event = window.CustomEvent; if (event) { event = new event(type, params); } else { event = window.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)); }; } function selection_dispatch(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 }; function select(selector) { return typeof selector === "string" ? new Selection([[document.querySelector(selector)]], [document.documentElement]) : new Selection([[selector]], root); } function selectAll(selector) { return typeof selector === "string" ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) : new Selection([selector == null ? [] : selector], root); } function touch(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(node, touch); } } return null; } function touches(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(node, touches[i]); } return points; } exports.creator = creator; 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 = defaultView; exports.customEvent = customEvent; Object.defineProperty(exports, '__esModule', { value: true }); })); },{}],15:[function(require,module,exports){ // https://d3js.org/d3-timer/ Version 1.0.3. 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 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() { 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, pokeDelay); frame = 1, setFrame(wake); } } function timeout$1(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; } function interval$1(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; } exports.now = now; exports.timer = timer; exports.timerFlush = timerFlush; exports.timeout = timeout$1; exports.interval = interval$1; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{}],16:[function(require,module,exports){ // https://d3js.org/d3-transition/ Version 1.0.2. Copyright 2016 Mike Bostock. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-selection'), require('d3-dispatch'), require('d3-timer'), require('d3-interpolate'), require('d3-color'), require('d3-ease')) : typeof define === 'function' && define.amd ? define(['exports', 'd3-selection', 'd3-dispatch', 'd3-timer', 'd3-interpolate', 'd3-color', 'd3-ease'], factory) : (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3,global.d3)); }(this, (function (exports,d3Selection,d3Dispatch,d3Timer,d3Interpolate,d3Color,d3Ease) { 'use strict'; var emptyOn = d3Dispatch.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 schedule(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(node, id) { var schedule = node.__transition; if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); return schedule; } function get(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 = d3Timer.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 d3Timer.timeout(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. d3Timer.timeout(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; } } function interrupt(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 === STARTED; 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; } function selection_interrupt(name) { return this.each(function() { interrupt(this, name); }); } function tweenRemove(id, name) { var tween0, tween1; return function() { var schedule = set(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(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 transition_tween(name, value) { var id = this._id; name += ""; if (arguments.length < 2) { var tween = get(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(this, id); (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); }); return function(node) { return get(node, id).value[name]; }; } function interpolate(a, b) { var c; return (typeof b === "number" ? d3Interpolate.interpolateNumber : b instanceof d3Color.color ? d3Interpolate.interpolateRgb : (c = d3Color.color(b)) ? (b = c, d3Interpolate.interpolateRgb) : d3Interpolate.interpolateString)(a, b); } function attrRemove(name) { return function() { this.removeAttribute(name); }; } function attrRemoveNS(fullname) { return function() { this.removeAttributeNS(fullname.space, fullname.local); }; } function attrConstant(name, interpolate, value1) { var value00, interpolate0; return function() { var value0 = this.getAttribute(name); return value0 === value1 ? null : value0 === value00 ? interpolate0 : interpolate0 = interpolate(value00 = value0, value1); }; } function attrConstantNS(fullname, interpolate, value1) { var value00, interpolate0; return function() { var value0 = this.getAttributeNS(fullname.space, fullname.local); return value0 === value1 ? null : value0 === value00 ? interpolate0 : interpolate0 = interpolate(value00 = value0, value1); }; } function attrFunction(name, interpolate, 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(value00 = value0, value10 = value1); }; } function attrFunctionNS(fullname, interpolate, 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(value00 = value0, value10 = value1); }; } function transition_attr(name, value) { var fullname = d3Selection.namespace(name), i = fullname === "transform" ? d3Interpolate.interpolateTransformSvg : interpolate; return this.attrTween(name, typeof value === "function" ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) : (fullname.local ? attrConstantNS : attrConstant)(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; } function transition_attrTween(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 = d3Selection.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; }; } function transition_delay(value) { var id = this._id; return arguments.length ? this.each((typeof value === "function" ? delayFunction : delayConstant)(id, value)) : get(this.node(), id).delay; } function durationFunction(id, value) { return function() { set(this, id).duration = +value.apply(this, arguments); }; } function durationConstant(id, value) { return value = +value, function() { set(this, id).duration = value; }; } function transition_duration(value) { var id = this._id; return arguments.length ? this.each((typeof value === "function" ? durationFunction : durationConstant)(id, value)) : get(this.node(), id).duration; } function easeConstant(id, value) { if (typeof value !== "function") throw new Error; return function() { set(this, id).ease = value; }; } function transition_ease(value) { var id = this._id; return arguments.length ? this.each(easeConstant(id, value)) : get(this.node(), id).ease; } function transition_filter(match) { if (typeof match !== "function") match = d3Selection.matcher(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); } function transition_merge(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(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(name) ? init : set; 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; }; } function transition_on(name, listener) { var id = this._id; return arguments.length < 2 ? get(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); }; } function transition_remove() { return this.on("end.remove", removeFunction(this._id)); } function transition_select(select) { var name = this._name, id = this._id; if (typeof select !== "function") select = d3Selection.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; schedule(subgroup[i], name, id, i, subgroup, get(node, id)); } } } return new Transition(subgroups, this._parents, name, id); } function transition_selectAll(select) { var name = this._name, id = this._id; if (typeof select !== "function") select = d3Selection.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]) { for (var children = select.call(node, node.__data__, i, group), child, inherit = get(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 = d3Selection.selection.prototype.constructor; function transition_selection() { return new Selection(this._groups, this._parents); } function styleRemove(name, interpolate) { var value00, value10, interpolate0; return function() { var style = d3Selection.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(value00 = value0, value10 = value1); }; } function styleRemoveEnd(name) { return function() { this.style.removeProperty(name); }; } function styleConstant(name, interpolate, value1) { var value00, interpolate0; return function() { var value0 = d3Selection.window(this).getComputedStyle(this, null).getPropertyValue(name); return value0 === value1 ? null : value0 === value00 ? interpolate0 : interpolate0 = interpolate(value00 = value0, value1); }; } function styleFunction(name, interpolate, value) { var value00, value10, interpolate0; return function() { var style = d3Selection.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(value00 = value0, value10 = value1); }; } function transition_style(name, value, priority) { var i = (name += "") === "transform" ? d3Interpolate.interpolateTransformCss : interpolate; return value == null ? this .styleTween(name, styleRemove(name, i)) .on("end.style." + name, styleRemoveEnd(name)) : this.styleTween(name, typeof value === "function" ? styleFunction(name, i, tweenValue(this, "style." + name, value)) : styleConstant(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; } function transition_styleTween(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(value) { return function() { this.textContent = value; }; } function textFunction(value) { return function() { var value1 = value(this); this.textContent = value1 == null ? "" : value1; }; } function transition_text(value) { return this.tween("text", typeof value === "function" ? textFunction(tweenValue(this, "text", value)) : textConstant(value == null ? "" : value + "")); } function transition_transition() { 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(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 d3Selection.selection().transition(name); } function newId() { return ++id; } var selection_prototype = d3Selection.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: d3Ease.easeCubicInOut }; function inherit(node, id) { var timing; while (!(timing = node.__transition) || !(timing = timing[id])) { if (!(node = node.parentNode)) { return defaultTiming.time = d3Timer.now(), defaultTiming; } } return timing; } function selection_transition(name) { var id, timing; if (name instanceof Transition) { id = name._id, name = name._name; } else { id = newId(), (timing = defaultTiming).time = d3Timer.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); } d3Selection.selection.prototype.interrupt = selection_interrupt; d3Selection.selection.prototype.transition = selection_transition; var root = [null]; function active(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, name, +i); } } } return null; } exports.transition = transition; exports.active = active; exports.interrupt = interrupt; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{"d3-color":4,"d3-dispatch":7,"d3-ease":9,"d3-interpolate":11,"d3-selection":14,"d3-timer":15}],17:[function(require,module,exports){ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.topojson = global.topojson || {}))); }(this, (function (exports) { 'use strict'; function noop() {} function transformAbsolute(transform) { if (!transform) return noop; var x0, y0, kx = transform.scale[0], ky = transform.scale[1], dx = transform.translate[0], dy = transform.translate[1]; return function(point, i) { if (!i) x0 = y0 = 0; point[0] = (x0 += point[0]) * kx + dx; point[1] = (y0 += point[1]) * ky + dy; }; } function transformRelative(transform) { if (!transform) return noop; var x0, y0, kx = transform.scale[0], ky = transform.scale[1], dx = transform.translate[0], dy = transform.translate[1]; return function(point, i) { if (!i) x0 = y0 = 0; var x1 = Math.round((point[0] - dx) / kx), y1 = Math.round((point[1] - dy) / ky); point[0] = x1 - x0; point[1] = y1 - y0; x0 = x1; y0 = y1; }; } function reverse(array, n) { var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; } function bisect(a, x) { var lo = 0, hi = a.length; while (lo < hi) { var mid = lo + hi >>> 1; if (a[mid] < x) lo = mid + 1; else hi = mid; } return lo; } function feature(topology, o) { return o.type === "GeometryCollection" ? { type: "FeatureCollection", features: o.geometries.map(function(o) { return feature$1(topology, o); }) } : feature$1(topology, o); } function feature$1(topology, o) { var f = { type: "Feature", id: o.id, properties: o.properties || {}, geometry: object(topology, o) }; if (o.id == null) delete f.id; return f; } function object(topology, o) { var absolute = transformAbsolute(topology.transform), arcs = topology.arcs; function arc(i, points) { if (points.length) points.pop(); for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) { points.push(p = a[k].slice()); absolute(p, k); } if (i < 0) reverse(points, n); } function point(p) { p = p.slice(); absolute(p, 0); return p; } function line(arcs) { var points = []; for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); if (points.length < 2) points.push(points[0].slice()); return points; } function ring(arcs) { var points = line(arcs); while (points.length < 4) points.push(points[0].slice()); return points; } function polygon(arcs) { return arcs.map(ring); } function geometry(o) { var t = o.type; return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)} : t in geometryType ? {type: t, coordinates: geometryType[t](o)} : null; } var geometryType = { Point: function(o) { return point(o.coordinates); }, MultiPoint: function(o) { return o.coordinates.map(point); }, LineString: function(o) { return line(o.arcs); }, MultiLineString: function(o) { return o.arcs.map(line); }, Polygon: function(o) { return polygon(o.arcs); }, MultiPolygon: function(o) { return o.arcs.map(polygon); } }; return geometry(o); } function stitchArcs(topology, arcs) { var stitchedArcs = {}, fragmentByStart = {}, fragmentByEnd = {}, fragments = [], emptyIndex = -1; // Stitch empty arcs first, since they may be subsumed by other arcs. arcs.forEach(function(i, j) { var arc = topology.arcs[i < 0 ? ~i : i], t; if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; } }); arcs.forEach(function(i) { var e = ends(i), start = e[0], end = e[1], f, g; if (f = fragmentByEnd[start]) { delete fragmentByEnd[f.end]; f.push(i); f.end = end; if (g = fragmentByStart[end]) { delete fragmentByStart[g.start]; var fg = g === f ? f : f.concat(g); fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; } else { fragmentByStart[f.start] = fragmentByEnd[f.end] = f; } } else if (f = fragmentByStart[end]) { delete fragmentByStart[f.start]; f.unshift(i); f.start = start; if (g = fragmentByEnd[start]) { delete fragmentByEnd[g.end]; var gf = g === f ? f : g.concat(f); fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; } else { fragmentByStart[f.start] = fragmentByEnd[f.end] = f; } } else { f = [i]; fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; } }); function ends(i) { var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); else p1 = arc[arc.length - 1]; return i < 0 ? [p1, p0] : [p0, p1]; } function flush(fragmentByEnd, fragmentByStart) { for (var k in fragmentByEnd) { var f = fragmentByEnd[k]; delete fragmentByStart[f.start]; delete f.start; delete f.end; f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); fragments.push(f); } } flush(fragmentByEnd, fragmentByStart); flush(fragmentByStart, fragmentByEnd); arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); return fragments; } function mesh(topology) { return object(topology, meshArcs.apply(this, arguments)); } function meshArcs(topology, o, filter) { var arcs = []; function arc(i) { var j = i < 0 ? ~i : i; (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); } function line(arcs) { arcs.forEach(arc); } function polygon(arcs) { arcs.forEach(line); } function geometry(o) { if (o.type === "GeometryCollection") o.geometries.forEach(geometry); else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs); } if (arguments.length > 1) { var geomsByArc = [], geom; var geometryType = { LineString: line, MultiLineString: polygon, Polygon: polygon, MultiPolygon: function(arcs) { arcs.forEach(polygon); } }; geometry(o); geomsByArc.forEach(arguments.length < 3 ? function(geoms) { arcs.push(geoms[0].i); } : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); } else { for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i); } return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)}; } function cartesianTriangleArea(triangle) { var a = triangle[0], b = triangle[1], c = triangle[2]; return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1])); } function ring(ring) { var i = -1, n = ring.length, a, b = ring[n - 1], area = 0; while (++i < n) { a = b; b = ring[i]; area += a[0] * b[1] - a[1] * b[0]; } return area / 2; } function merge(topology) { return object(topology, mergeArcs.apply(this, arguments)); } function mergeArcs(topology, objects) { var polygonsByArc = {}, polygons = [], components = []; objects.forEach(function(o) { if (o.type === "Polygon") register(o.arcs); else if (o.type === "MultiPolygon") o.arcs.forEach(register); }); function register(polygon) { polygon.forEach(function(ring$$) { ring$$.forEach(function(arc) { (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); }); }); polygons.push(polygon); } function area(ring$$) { return Math.abs(ring(object(topology, {type: "Polygon", arcs: [ring$$]}).coordinates[0])); } polygons.forEach(function(polygon) { if (!polygon._) { var component = [], neighbors = [polygon]; polygon._ = 1; components.push(component); while (polygon = neighbors.pop()) { component.push(polygon); polygon.forEach(function(ring$$) { ring$$.forEach(function(arc) { polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { if (!polygon._) { polygon._ = 1; neighbors.push(polygon); } }); }); }); } } }); polygons.forEach(function(polygon) { delete polygon._; }); return { type: "MultiPolygon", arcs: components.map(function(polygons) { var arcs = [], n; // Extract the exterior (unique) arcs. polygons.forEach(function(polygon) { polygon.forEach(function(ring$$) { ring$$.forEach(function(arc) { if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { arcs.push(arc); } }); }); }); // Stitch the arcs into one or more rings. arcs = stitchArcs(topology, arcs); // If more than one ring is returned, // at most one of these rings can be the exterior; // choose the one with the greatest absolute area. if ((n = arcs.length) > 1) { for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) { if ((ki = area(arcs[i])) > k) { t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki; } } } return arcs; }) }; } function neighbors(objects) { var indexesByArc = {}, // arc index -> array of object indexes neighbors = objects.map(function() { return []; }); function line(arcs, i) { arcs.forEach(function(a) { if (a < 0) a = ~a; var o = indexesByArc[a]; if (o) o.push(i); else indexesByArc[a] = [i]; }); } function polygon(arcs, i) { arcs.forEach(function(arc) { line(arc, i); }); } function geometry(o, i) { if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); else if (o.type in geometryType) geometryType[o.type](o.arcs, i); } var geometryType = { LineString: line, MultiLineString: polygon, Polygon: polygon, MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } }; objects.forEach(geometry); for (var i in indexesByArc) { for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { for (var k = j + 1; k < m; ++k) { var ij = indexes[j], ik = indexes[k], n; if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); } } } return neighbors; } function compareArea(a, b) { return a[1][2] - b[1][2]; } function minAreaHeap() { var heap = {}, array = [], size = 0; heap.push = function(object) { up(array[object._ = size] = object, size++); return size; }; heap.pop = function() { if (size <= 0) return; var removed = array[0], object; if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0); return removed; }; heap.remove = function(removed) { var i = removed._, object; if (array[i] !== removed) return; // invalid request if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i); return i; }; function up(object, i) { while (i > 0) { var j = ((i + 1) >> 1) - 1, parent = array[j]; if (compareArea(object, parent) >= 0) break; array[parent._ = i] = parent; array[object._ = i = j] = object; } } function down(object, i) { while (true) { var r = (i + 1) << 1, l = r - 1, j = i, child = array[j]; if (l < size && compareArea(array[l], child) < 0) child = array[j = l]; if (r < size && compareArea(array[r], child) < 0) child = array[j = r]; if (j === i) break; array[child._ = i] = child; array[object._ = i = j] = object; } } return heap; } function presimplify(topology, triangleArea) { var absolute = transformAbsolute(topology.transform), relative = transformRelative(topology.transform), heap = minAreaHeap(); if (!triangleArea) triangleArea = cartesianTriangleArea; topology.arcs.forEach(function(arc) { var triangles = [], maxArea = 0, triangle, i, n, p; // To store each point’s effective area, we create a new array rather than // extending the passed-in point to workaround a Chrome/V8 bug (getting // stuck in smi mode). For midpoints, the initial effective area of // Infinity will be computed in the next step. for (i = 0, n = arc.length; i < n; ++i) { p = arc[i]; absolute(arc[i] = [p[0], p[1], Infinity], i); } for (i = 1, n = arc.length - 1; i < n; ++i) { triangle = arc.slice(i - 1, i + 2); triangle[1][2] = triangleArea(triangle); triangles.push(triangle); heap.push(triangle); } for (i = 0, n = triangles.length; i < n; ++i) { triangle = triangles[i]; triangle.previous = triangles[i - 1]; triangle.next = triangles[i + 1]; } while (triangle = heap.pop()) { var previous = triangle.previous, next = triangle.next; // If the area of the current point is less than that of the previous point // to be eliminated, use the latter's area instead. This ensures that the // current point cannot be eliminated without eliminating previously- // eliminated points. if (triangle[1][2] < maxArea) triangle[1][2] = maxArea; else maxArea = triangle[1][2]; if (previous) { previous.next = next; previous[2] = triangle[2]; update(previous); } if (next) { next.previous = previous; next[0] = triangle[0]; update(next); } } arc.forEach(relative); }); function update(triangle) { heap.remove(triangle); triangle[1][2] = triangleArea(triangle); heap.push(triangle); } return topology; } var version = "1.6.27"; exports.version = version; exports.mesh = mesh; exports.meshArcs = meshArcs; exports.merge = merge; exports.mergeArcs = mergeArcs; exports.feature = feature; exports.neighbors = neighbors; exports.presimplify = presimplify; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{}]},{},[1]);