├── D3_netcdfjs_01.gif ├── D3_netcdfjs_02.gif ├── LICENSE.md ├── README.md ├── antimeridian_cutting_01.html ├── d3_contours_01.html ├── d3_contours_02.html ├── etopo60.nc ├── etopo60_2.nc ├── interactive_orthographic_01.html ├── interactive_orthographic_02.html ├── interactive_orthographic_03.html ├── js ├── d3-array@1 ├── d3-collection@1 ├── d3-color@1 ├── d3-contour@1 ├── d3-dispatch@1 ├── d3-drag@1 ├── d3-geo-projection@2 ├── d3-geo@1 ├── d3-interpolate@1 ├── d3-legend.min.js ├── d3-request@1 ├── d3-scale@1 ├── d3-selection@1 ├── d3-transition@1 ├── d3-zoom@1 ├── netcdfjs.js ├── netcdfjs_patched.js ├── numjs.js ├── topojson@1 ├── topojson@3 └── versor@0 ├── myreadme ├── navy_winds_0.nc ├── navy_winds_2.nc ├── netcdfjs_01.html ├── netcdfjs_02.html ├── netcdfjs_03.html ├── netcdfjs_04.html ├── netcdfjs_05.html ├── raster-pixels-page_01.html ├── raster-pixels-page_02.html ├── sfctmp.tiff ├── synchronized_maps_00.html ├── synchronized_maps_01.html ├── synchronized_maps_02.html ├── synchronized_maps_03.html ├── temp.nc ├── tz850.tiff ├── uwnd.nc ├── uwnd.tiff └── world-110m.json /D3_netcdfjs_01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/D3_netcdfjs_01.gif -------------------------------------------------------------------------------- /D3_netcdfjs_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/D3_netcdfjs_02.gif -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Patrick Brockmann LSCE / IPSL 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # D3_netcdfjs 2 | d3.contours from netCDF file as synchronized maps 3 | 4 | 5 | 6 |
7 | 8 | -------------------------------------------------------------------------------- /antimeridian_cutting_01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 66 | -------------------------------------------------------------------------------- /d3_contours_01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /d3_contours_02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /etopo60.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/etopo60.nc -------------------------------------------------------------------------------- /etopo60_2.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/etopo60_2.nc -------------------------------------------------------------------------------- /interactive_orthographic_01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /interactive_orthographic_02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /interactive_orthographic_03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 21 | 22 | 23 | 24 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /js/d3-array@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-array/ Version 1.2.1. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 4 | typeof define === 'function' && define.amd ? define(['exports'], factory) : 5 | (factory((global.d3 = global.d3 || {}))); 6 | }(this, (function (exports) { 'use strict'; 7 | 8 | var ascending = function(a, b) { 9 | return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; 10 | }; 11 | 12 | var bisector = function(compare) { 13 | if (compare.length === 1) compare = ascendingComparator(compare); 14 | return { 15 | left: function(a, x, lo, hi) { 16 | if (lo == null) lo = 0; 17 | if (hi == null) hi = a.length; 18 | while (lo < hi) { 19 | var mid = lo + hi >>> 1; 20 | if (compare(a[mid], x) < 0) lo = mid + 1; 21 | else hi = mid; 22 | } 23 | return lo; 24 | }, 25 | right: function(a, x, lo, hi) { 26 | if (lo == null) lo = 0; 27 | if (hi == null) hi = a.length; 28 | while (lo < hi) { 29 | var mid = lo + hi >>> 1; 30 | if (compare(a[mid], x) > 0) hi = mid; 31 | else lo = mid + 1; 32 | } 33 | return lo; 34 | } 35 | }; 36 | }; 37 | 38 | function ascendingComparator(f) { 39 | return function(d, x) { 40 | return ascending(f(d), x); 41 | }; 42 | } 43 | 44 | var ascendingBisect = bisector(ascending); 45 | var bisectRight = ascendingBisect.right; 46 | var bisectLeft = ascendingBisect.left; 47 | 48 | var pairs = function(array, f) { 49 | if (f == null) f = pair; 50 | var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); 51 | while (i < n) pairs[i] = f(p, p = array[++i]); 52 | return pairs; 53 | }; 54 | 55 | function pair(a, b) { 56 | return [a, b]; 57 | } 58 | 59 | var cross = function(values0, values1, reduce) { 60 | var n0 = values0.length, 61 | n1 = values1.length, 62 | values = new Array(n0 * n1), 63 | i0, 64 | i1, 65 | i, 66 | value0; 67 | 68 | if (reduce == null) reduce = pair; 69 | 70 | for (i0 = i = 0; i0 < n0; ++i0) { 71 | for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { 72 | values[i] = reduce(value0, values1[i1]); 73 | } 74 | } 75 | 76 | return values; 77 | }; 78 | 79 | var descending = function(a, b) { 80 | return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; 81 | }; 82 | 83 | var number = function(x) { 84 | return x === null ? NaN : +x; 85 | }; 86 | 87 | var variance = function(values, valueof) { 88 | var n = values.length, 89 | m = 0, 90 | i = -1, 91 | mean = 0, 92 | value, 93 | delta, 94 | sum = 0; 95 | 96 | if (valueof == null) { 97 | while (++i < n) { 98 | if (!isNaN(value = number(values[i]))) { 99 | delta = value - mean; 100 | mean += delta / ++m; 101 | sum += delta * (value - mean); 102 | } 103 | } 104 | } 105 | 106 | else { 107 | while (++i < n) { 108 | if (!isNaN(value = number(valueof(values[i], i, values)))) { 109 | delta = value - mean; 110 | mean += delta / ++m; 111 | sum += delta * (value - mean); 112 | } 113 | } 114 | } 115 | 116 | if (m > 1) return sum / (m - 1); 117 | }; 118 | 119 | var deviation = function(array, f) { 120 | var v = variance(array, f); 121 | return v ? Math.sqrt(v) : v; 122 | }; 123 | 124 | var extent = function(values, valueof) { 125 | var n = values.length, 126 | i = -1, 127 | value, 128 | min, 129 | max; 130 | 131 | if (valueof == null) { 132 | while (++i < n) { // Find the first comparable value. 133 | if ((value = values[i]) != null && value >= value) { 134 | min = max = value; 135 | while (++i < n) { // Compare the remaining values. 136 | if ((value = values[i]) != null) { 137 | if (min > value) min = value; 138 | if (max < value) max = value; 139 | } 140 | } 141 | } 142 | } 143 | } 144 | 145 | else { 146 | while (++i < n) { // Find the first comparable value. 147 | if ((value = valueof(values[i], i, values)) != null && value >= value) { 148 | min = max = value; 149 | while (++i < n) { // Compare the remaining values. 150 | if ((value = valueof(values[i], i, values)) != null) { 151 | if (min > value) min = value; 152 | if (max < value) max = value; 153 | } 154 | } 155 | } 156 | } 157 | } 158 | 159 | return [min, max]; 160 | }; 161 | 162 | var array = Array.prototype; 163 | 164 | var slice = array.slice; 165 | var map = array.map; 166 | 167 | var constant = function(x) { 168 | return function() { 169 | return x; 170 | }; 171 | }; 172 | 173 | var identity = function(x) { 174 | return x; 175 | }; 176 | 177 | var range = function(start, stop, step) { 178 | start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; 179 | 180 | var i = -1, 181 | n = Math.max(0, Math.ceil((stop - start) / step)) | 0, 182 | range = new Array(n); 183 | 184 | while (++i < n) { 185 | range[i] = start + i * step; 186 | } 187 | 188 | return range; 189 | }; 190 | 191 | var e10 = Math.sqrt(50); 192 | var e5 = Math.sqrt(10); 193 | var e2 = Math.sqrt(2); 194 | 195 | var ticks = function(start, stop, count) { 196 | var reverse, 197 | i = -1, 198 | n, 199 | ticks, 200 | step; 201 | 202 | stop = +stop, start = +start, count = +count; 203 | if (start === stop && count > 0) return [start]; 204 | if (reverse = stop < start) n = start, start = stop, stop = n; 205 | if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; 206 | 207 | if (step > 0) { 208 | start = Math.ceil(start / step); 209 | stop = Math.floor(stop / step); 210 | ticks = new Array(n = Math.ceil(stop - start + 1)); 211 | while (++i < n) ticks[i] = (start + i) * step; 212 | } else { 213 | start = Math.floor(start * step); 214 | stop = Math.ceil(stop * step); 215 | ticks = new Array(n = Math.ceil(start - stop + 1)); 216 | while (++i < n) ticks[i] = (start - i) / step; 217 | } 218 | 219 | if (reverse) ticks.reverse(); 220 | 221 | return ticks; 222 | }; 223 | 224 | function tickIncrement(start, stop, count) { 225 | var step = (stop - start) / Math.max(0, count), 226 | power = Math.floor(Math.log(step) / Math.LN10), 227 | error = step / Math.pow(10, power); 228 | return power >= 0 229 | ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) 230 | : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); 231 | } 232 | 233 | function tickStep(start, stop, count) { 234 | var step0 = Math.abs(stop - start) / Math.max(0, count), 235 | step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), 236 | error = step0 / step1; 237 | if (error >= e10) step1 *= 10; 238 | else if (error >= e5) step1 *= 5; 239 | else if (error >= e2) step1 *= 2; 240 | return stop < start ? -step1 : step1; 241 | } 242 | 243 | var sturges = function(values) { 244 | return Math.ceil(Math.log(values.length) / Math.LN2) + 1; 245 | }; 246 | 247 | var histogram = function() { 248 | var value = identity, 249 | domain = extent, 250 | threshold = sturges; 251 | 252 | function histogram(data) { 253 | var i, 254 | n = data.length, 255 | x, 256 | values = new Array(n); 257 | 258 | for (i = 0; i < n; ++i) { 259 | values[i] = value(data[i], i, data); 260 | } 261 | 262 | var xz = domain(values), 263 | x0 = xz[0], 264 | x1 = xz[1], 265 | tz = threshold(values, x0, x1); 266 | 267 | // Convert number of thresholds into uniform thresholds. 268 | if (!Array.isArray(tz)) { 269 | tz = tickStep(x0, x1, tz); 270 | tz = range(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive 271 | } 272 | 273 | // Remove any thresholds outside the domain. 274 | var m = tz.length; 275 | while (tz[0] <= x0) tz.shift(), --m; 276 | while (tz[m - 1] > x1) tz.pop(), --m; 277 | 278 | var bins = new Array(m + 1), 279 | bin; 280 | 281 | // Initialize bins. 282 | for (i = 0; i <= m; ++i) { 283 | bin = bins[i] = []; 284 | bin.x0 = i > 0 ? tz[i - 1] : x0; 285 | bin.x1 = i < m ? tz[i] : x1; 286 | } 287 | 288 | // Assign data to bins by value, ignoring any outside the domain. 289 | for (i = 0; i < n; ++i) { 290 | x = values[i]; 291 | if (x0 <= x && x <= x1) { 292 | bins[bisectRight(tz, x, 0, m)].push(data[i]); 293 | } 294 | } 295 | 296 | return bins; 297 | } 298 | 299 | histogram.value = function(_) { 300 | return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; 301 | }; 302 | 303 | histogram.domain = function(_) { 304 | return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; 305 | }; 306 | 307 | histogram.thresholds = function(_) { 308 | return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; 309 | }; 310 | 311 | return histogram; 312 | }; 313 | 314 | var quantile = function(values, p, valueof) { 315 | if (valueof == null) valueof = number; 316 | if (!(n = values.length)) return; 317 | if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); 318 | if (p >= 1) return +valueof(values[n - 1], n - 1, values); 319 | var n, 320 | i = (n - 1) * p, 321 | i0 = Math.floor(i), 322 | value0 = +valueof(values[i0], i0, values), 323 | value1 = +valueof(values[i0 + 1], i0 + 1, values); 324 | return value0 + (value1 - value0) * (i - i0); 325 | }; 326 | 327 | var freedmanDiaconis = function(values, min, max) { 328 | values = map.call(values, number).sort(ascending); 329 | return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3))); 330 | }; 331 | 332 | var scott = function(values, min, max) { 333 | return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); 334 | }; 335 | 336 | var max = function(values, valueof) { 337 | var n = values.length, 338 | i = -1, 339 | value, 340 | max; 341 | 342 | if (valueof == null) { 343 | while (++i < n) { // Find the first comparable value. 344 | if ((value = values[i]) != null && value >= value) { 345 | max = value; 346 | while (++i < n) { // Compare the remaining values. 347 | if ((value = values[i]) != null && value > max) { 348 | max = value; 349 | } 350 | } 351 | } 352 | } 353 | } 354 | 355 | else { 356 | while (++i < n) { // Find the first comparable value. 357 | if ((value = valueof(values[i], i, values)) != null && value >= value) { 358 | max = value; 359 | while (++i < n) { // Compare the remaining values. 360 | if ((value = valueof(values[i], i, values)) != null && value > max) { 361 | max = value; 362 | } 363 | } 364 | } 365 | } 366 | } 367 | 368 | return max; 369 | }; 370 | 371 | var mean = function(values, valueof) { 372 | var n = values.length, 373 | m = n, 374 | i = -1, 375 | value, 376 | sum = 0; 377 | 378 | if (valueof == null) { 379 | while (++i < n) { 380 | if (!isNaN(value = number(values[i]))) sum += value; 381 | else --m; 382 | } 383 | } 384 | 385 | else { 386 | while (++i < n) { 387 | if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; 388 | else --m; 389 | } 390 | } 391 | 392 | if (m) return sum / m; 393 | }; 394 | 395 | var median = function(values, valueof) { 396 | var n = values.length, 397 | i = -1, 398 | value, 399 | numbers = []; 400 | 401 | if (valueof == null) { 402 | while (++i < n) { 403 | if (!isNaN(value = number(values[i]))) { 404 | numbers.push(value); 405 | } 406 | } 407 | } 408 | 409 | else { 410 | while (++i < n) { 411 | if (!isNaN(value = number(valueof(values[i], i, values)))) { 412 | numbers.push(value); 413 | } 414 | } 415 | } 416 | 417 | return quantile(numbers.sort(ascending), 0.5); 418 | }; 419 | 420 | var merge = function(arrays) { 421 | var n = arrays.length, 422 | m, 423 | i = -1, 424 | j = 0, 425 | merged, 426 | array; 427 | 428 | while (++i < n) j += arrays[i].length; 429 | merged = new Array(j); 430 | 431 | while (--n >= 0) { 432 | array = arrays[n]; 433 | m = array.length; 434 | while (--m >= 0) { 435 | merged[--j] = array[m]; 436 | } 437 | } 438 | 439 | return merged; 440 | }; 441 | 442 | var min = function(values, valueof) { 443 | var n = values.length, 444 | i = -1, 445 | value, 446 | min; 447 | 448 | if (valueof == null) { 449 | while (++i < n) { // Find the first comparable value. 450 | if ((value = values[i]) != null && value >= value) { 451 | min = value; 452 | while (++i < n) { // Compare the remaining values. 453 | if ((value = values[i]) != null && min > value) { 454 | min = value; 455 | } 456 | } 457 | } 458 | } 459 | } 460 | 461 | else { 462 | while (++i < n) { // Find the first comparable value. 463 | if ((value = valueof(values[i], i, values)) != null && value >= value) { 464 | min = value; 465 | while (++i < n) { // Compare the remaining values. 466 | if ((value = valueof(values[i], i, values)) != null && min > value) { 467 | min = value; 468 | } 469 | } 470 | } 471 | } 472 | } 473 | 474 | return min; 475 | }; 476 | 477 | var permute = function(array, indexes) { 478 | var i = indexes.length, permutes = new Array(i); 479 | while (i--) permutes[i] = array[indexes[i]]; 480 | return permutes; 481 | }; 482 | 483 | var scan = function(values, compare) { 484 | if (!(n = values.length)) return; 485 | var n, 486 | i = 0, 487 | j = 0, 488 | xi, 489 | xj = values[j]; 490 | 491 | if (compare == null) compare = ascending; 492 | 493 | while (++i < n) { 494 | if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { 495 | xj = xi, j = i; 496 | } 497 | } 498 | 499 | if (compare(xj, xj) === 0) return j; 500 | }; 501 | 502 | var shuffle = function(array, i0, i1) { 503 | var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), 504 | t, 505 | i; 506 | 507 | while (m) { 508 | i = Math.random() * m-- | 0; 509 | t = array[m + i0]; 510 | array[m + i0] = array[i + i0]; 511 | array[i + i0] = t; 512 | } 513 | 514 | return array; 515 | }; 516 | 517 | var sum = function(values, valueof) { 518 | var n = values.length, 519 | i = -1, 520 | value, 521 | sum = 0; 522 | 523 | if (valueof == null) { 524 | while (++i < n) { 525 | if (value = +values[i]) sum += value; // Note: zero and null are equivalent. 526 | } 527 | } 528 | 529 | else { 530 | while (++i < n) { 531 | if (value = +valueof(values[i], i, values)) sum += value; 532 | } 533 | } 534 | 535 | return sum; 536 | }; 537 | 538 | var transpose = function(matrix) { 539 | if (!(n = matrix.length)) return []; 540 | for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { 541 | for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { 542 | row[j] = matrix[j][i]; 543 | } 544 | } 545 | return transpose; 546 | }; 547 | 548 | function length(d) { 549 | return d.length; 550 | } 551 | 552 | var zip = function() { 553 | return transpose(arguments); 554 | }; 555 | 556 | exports.bisect = bisectRight; 557 | exports.bisectRight = bisectRight; 558 | exports.bisectLeft = bisectLeft; 559 | exports.ascending = ascending; 560 | exports.bisector = bisector; 561 | exports.cross = cross; 562 | exports.descending = descending; 563 | exports.deviation = deviation; 564 | exports.extent = extent; 565 | exports.histogram = histogram; 566 | exports.thresholdFreedmanDiaconis = freedmanDiaconis; 567 | exports.thresholdScott = scott; 568 | exports.thresholdSturges = sturges; 569 | exports.max = max; 570 | exports.mean = mean; 571 | exports.median = median; 572 | exports.merge = merge; 573 | exports.min = min; 574 | exports.pairs = pairs; 575 | exports.permute = permute; 576 | exports.quantile = quantile; 577 | exports.range = range; 578 | exports.scan = scan; 579 | exports.shuffle = shuffle; 580 | exports.sum = sum; 581 | exports.ticks = ticks; 582 | exports.tickIncrement = tickIncrement; 583 | exports.tickStep = tickStep; 584 | exports.transpose = transpose; 585 | exports.variance = variance; 586 | exports.zip = zip; 587 | 588 | Object.defineProperty(exports, '__esModule', { value: true }); 589 | 590 | }))); 591 | -------------------------------------------------------------------------------- /js/d3-collection@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-collection/ Version 1.0.4. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 4 | typeof define === 'function' && define.amd ? define(['exports'], factory) : 5 | (factory((global.d3 = global.d3 || {}))); 6 | }(this, (function (exports) { 'use strict'; 7 | 8 | var prefix = "$"; 9 | 10 | function Map() {} 11 | 12 | Map.prototype = map.prototype = { 13 | constructor: Map, 14 | has: function(key) { 15 | return (prefix + key) in this; 16 | }, 17 | get: function(key) { 18 | return this[prefix + key]; 19 | }, 20 | set: function(key, value) { 21 | this[prefix + key] = value; 22 | return this; 23 | }, 24 | remove: function(key) { 25 | var property = prefix + key; 26 | return property in this && delete this[property]; 27 | }, 28 | clear: function() { 29 | for (var property in this) if (property[0] === prefix) delete this[property]; 30 | }, 31 | keys: function() { 32 | var keys = []; 33 | for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); 34 | return keys; 35 | }, 36 | values: function() { 37 | var values = []; 38 | for (var property in this) if (property[0] === prefix) values.push(this[property]); 39 | return values; 40 | }, 41 | entries: function() { 42 | var entries = []; 43 | for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); 44 | return entries; 45 | }, 46 | size: function() { 47 | var size = 0; 48 | for (var property in this) if (property[0] === prefix) ++size; 49 | return size; 50 | }, 51 | empty: function() { 52 | for (var property in this) if (property[0] === prefix) return false; 53 | return true; 54 | }, 55 | each: function(f) { 56 | for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); 57 | } 58 | }; 59 | 60 | function map(object, f) { 61 | var map = new Map; 62 | 63 | // Copy constructor. 64 | if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); 65 | 66 | // Index array by numeric index or specified key function. 67 | else if (Array.isArray(object)) { 68 | var i = -1, 69 | n = object.length, 70 | o; 71 | 72 | if (f == null) while (++i < n) map.set(i, object[i]); 73 | else while (++i < n) map.set(f(o = object[i], i, object), o); 74 | } 75 | 76 | // Convert object to map. 77 | else if (object) for (var key in object) map.set(key, object[key]); 78 | 79 | return map; 80 | } 81 | 82 | var nest = function() { 83 | var keys = [], 84 | sortKeys = [], 85 | sortValues, 86 | rollup, 87 | nest; 88 | 89 | function apply(array, depth, createResult, setResult) { 90 | if (depth >= keys.length) { 91 | if (sortValues != null) array.sort(sortValues); 92 | return rollup != null ? rollup(array) : array; 93 | } 94 | 95 | var i = -1, 96 | n = array.length, 97 | key = keys[depth++], 98 | keyValue, 99 | value, 100 | valuesByKey = map(), 101 | values, 102 | result = createResult(); 103 | 104 | while (++i < n) { 105 | if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { 106 | values.push(value); 107 | } else { 108 | valuesByKey.set(keyValue, [value]); 109 | } 110 | } 111 | 112 | valuesByKey.each(function(values, key) { 113 | setResult(result, key, apply(values, depth, createResult, setResult)); 114 | }); 115 | 116 | return result; 117 | } 118 | 119 | function entries(map$$1, depth) { 120 | if (++depth > keys.length) return map$$1; 121 | var array, sortKey = sortKeys[depth - 1]; 122 | if (rollup != null && depth >= keys.length) array = map$$1.entries(); 123 | else array = [], map$$1.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); 124 | return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; 125 | } 126 | 127 | return nest = { 128 | object: function(array) { return apply(array, 0, createObject, setObject); }, 129 | map: function(array) { return apply(array, 0, createMap, setMap); }, 130 | entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, 131 | key: function(d) { keys.push(d); return nest; }, 132 | sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, 133 | sortValues: function(order) { sortValues = order; return nest; }, 134 | rollup: function(f) { rollup = f; return nest; } 135 | }; 136 | }; 137 | 138 | function createObject() { 139 | return {}; 140 | } 141 | 142 | function setObject(object, key, value) { 143 | object[key] = value; 144 | } 145 | 146 | function createMap() { 147 | return map(); 148 | } 149 | 150 | function setMap(map$$1, key, value) { 151 | map$$1.set(key, value); 152 | } 153 | 154 | function Set() {} 155 | 156 | var proto = map.prototype; 157 | 158 | Set.prototype = set.prototype = { 159 | constructor: Set, 160 | has: proto.has, 161 | add: function(value) { 162 | value += ""; 163 | this[prefix + value] = value; 164 | return this; 165 | }, 166 | remove: proto.remove, 167 | clear: proto.clear, 168 | values: proto.keys, 169 | size: proto.size, 170 | empty: proto.empty, 171 | each: proto.each 172 | }; 173 | 174 | function set(object, f) { 175 | var set = new Set; 176 | 177 | // Copy constructor. 178 | if (object instanceof Set) object.each(function(value) { set.add(value); }); 179 | 180 | // Otherwise, assume it’s an array. 181 | else if (object) { 182 | var i = -1, n = object.length; 183 | if (f == null) while (++i < n) set.add(object[i]); 184 | else while (++i < n) set.add(f(object[i], i, object)); 185 | } 186 | 187 | return set; 188 | } 189 | 190 | var keys = function(map) { 191 | var keys = []; 192 | for (var key in map) keys.push(key); 193 | return keys; 194 | }; 195 | 196 | var values = function(map) { 197 | var values = []; 198 | for (var key in map) values.push(map[key]); 199 | return values; 200 | }; 201 | 202 | var entries = function(map) { 203 | var entries = []; 204 | for (var key in map) entries.push({key: key, value: map[key]}); 205 | return entries; 206 | }; 207 | 208 | exports.nest = nest; 209 | exports.set = set; 210 | exports.map = map; 211 | exports.keys = keys; 212 | exports.values = values; 213 | exports.entries = entries; 214 | 215 | Object.defineProperty(exports, '__esModule', { value: true }); 216 | 217 | }))); 218 | -------------------------------------------------------------------------------- /js/d3-color@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-color/ Version 1.0.3. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 4 | typeof define === 'function' && define.amd ? define(['exports'], factory) : 5 | (factory((global.d3 = global.d3 || {}))); 6 | }(this, (function (exports) { 'use strict'; 7 | 8 | var define = function(constructor, factory, prototype) { 9 | constructor.prototype = factory.prototype = prototype; 10 | prototype.constructor = constructor; 11 | }; 12 | 13 | function extend(parent, definition) { 14 | var prototype = Object.create(parent.prototype); 15 | for (var key in definition) prototype[key] = definition[key]; 16 | return prototype; 17 | } 18 | 19 | function Color() {} 20 | 21 | var darker = 0.7; 22 | var brighter = 1 / darker; 23 | 24 | var reI = "\\s*([+-]?\\d+)\\s*"; 25 | var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*"; 26 | var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; 27 | var reHex3 = /^#([0-9a-f]{3})$/; 28 | var reHex6 = /^#([0-9a-f]{6})$/; 29 | var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"); 30 | var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"); 31 | var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"); 32 | var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"); 33 | var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"); 34 | var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); 35 | 36 | var named = { 37 | aliceblue: 0xf0f8ff, 38 | antiquewhite: 0xfaebd7, 39 | aqua: 0x00ffff, 40 | aquamarine: 0x7fffd4, 41 | azure: 0xf0ffff, 42 | beige: 0xf5f5dc, 43 | bisque: 0xffe4c4, 44 | black: 0x000000, 45 | blanchedalmond: 0xffebcd, 46 | blue: 0x0000ff, 47 | blueviolet: 0x8a2be2, 48 | brown: 0xa52a2a, 49 | burlywood: 0xdeb887, 50 | cadetblue: 0x5f9ea0, 51 | chartreuse: 0x7fff00, 52 | chocolate: 0xd2691e, 53 | coral: 0xff7f50, 54 | cornflowerblue: 0x6495ed, 55 | cornsilk: 0xfff8dc, 56 | crimson: 0xdc143c, 57 | cyan: 0x00ffff, 58 | darkblue: 0x00008b, 59 | darkcyan: 0x008b8b, 60 | darkgoldenrod: 0xb8860b, 61 | darkgray: 0xa9a9a9, 62 | darkgreen: 0x006400, 63 | darkgrey: 0xa9a9a9, 64 | darkkhaki: 0xbdb76b, 65 | darkmagenta: 0x8b008b, 66 | darkolivegreen: 0x556b2f, 67 | darkorange: 0xff8c00, 68 | darkorchid: 0x9932cc, 69 | darkred: 0x8b0000, 70 | darksalmon: 0xe9967a, 71 | darkseagreen: 0x8fbc8f, 72 | darkslateblue: 0x483d8b, 73 | darkslategray: 0x2f4f4f, 74 | darkslategrey: 0x2f4f4f, 75 | darkturquoise: 0x00ced1, 76 | darkviolet: 0x9400d3, 77 | deeppink: 0xff1493, 78 | deepskyblue: 0x00bfff, 79 | dimgray: 0x696969, 80 | dimgrey: 0x696969, 81 | dodgerblue: 0x1e90ff, 82 | firebrick: 0xb22222, 83 | floralwhite: 0xfffaf0, 84 | forestgreen: 0x228b22, 85 | fuchsia: 0xff00ff, 86 | gainsboro: 0xdcdcdc, 87 | ghostwhite: 0xf8f8ff, 88 | gold: 0xffd700, 89 | goldenrod: 0xdaa520, 90 | gray: 0x808080, 91 | green: 0x008000, 92 | greenyellow: 0xadff2f, 93 | grey: 0x808080, 94 | honeydew: 0xf0fff0, 95 | hotpink: 0xff69b4, 96 | indianred: 0xcd5c5c, 97 | indigo: 0x4b0082, 98 | ivory: 0xfffff0, 99 | khaki: 0xf0e68c, 100 | lavender: 0xe6e6fa, 101 | lavenderblush: 0xfff0f5, 102 | lawngreen: 0x7cfc00, 103 | lemonchiffon: 0xfffacd, 104 | lightblue: 0xadd8e6, 105 | lightcoral: 0xf08080, 106 | lightcyan: 0xe0ffff, 107 | lightgoldenrodyellow: 0xfafad2, 108 | lightgray: 0xd3d3d3, 109 | lightgreen: 0x90ee90, 110 | lightgrey: 0xd3d3d3, 111 | lightpink: 0xffb6c1, 112 | lightsalmon: 0xffa07a, 113 | lightseagreen: 0x20b2aa, 114 | lightskyblue: 0x87cefa, 115 | lightslategray: 0x778899, 116 | lightslategrey: 0x778899, 117 | lightsteelblue: 0xb0c4de, 118 | lightyellow: 0xffffe0, 119 | lime: 0x00ff00, 120 | limegreen: 0x32cd32, 121 | linen: 0xfaf0e6, 122 | magenta: 0xff00ff, 123 | maroon: 0x800000, 124 | mediumaquamarine: 0x66cdaa, 125 | mediumblue: 0x0000cd, 126 | mediumorchid: 0xba55d3, 127 | mediumpurple: 0x9370db, 128 | mediumseagreen: 0x3cb371, 129 | mediumslateblue: 0x7b68ee, 130 | mediumspringgreen: 0x00fa9a, 131 | mediumturquoise: 0x48d1cc, 132 | mediumvioletred: 0xc71585, 133 | midnightblue: 0x191970, 134 | mintcream: 0xf5fffa, 135 | mistyrose: 0xffe4e1, 136 | moccasin: 0xffe4b5, 137 | navajowhite: 0xffdead, 138 | navy: 0x000080, 139 | oldlace: 0xfdf5e6, 140 | olive: 0x808000, 141 | olivedrab: 0x6b8e23, 142 | orange: 0xffa500, 143 | orangered: 0xff4500, 144 | orchid: 0xda70d6, 145 | palegoldenrod: 0xeee8aa, 146 | palegreen: 0x98fb98, 147 | paleturquoise: 0xafeeee, 148 | palevioletred: 0xdb7093, 149 | papayawhip: 0xffefd5, 150 | peachpuff: 0xffdab9, 151 | peru: 0xcd853f, 152 | pink: 0xffc0cb, 153 | plum: 0xdda0dd, 154 | powderblue: 0xb0e0e6, 155 | purple: 0x800080, 156 | rebeccapurple: 0x663399, 157 | red: 0xff0000, 158 | rosybrown: 0xbc8f8f, 159 | royalblue: 0x4169e1, 160 | saddlebrown: 0x8b4513, 161 | salmon: 0xfa8072, 162 | sandybrown: 0xf4a460, 163 | seagreen: 0x2e8b57, 164 | seashell: 0xfff5ee, 165 | sienna: 0xa0522d, 166 | silver: 0xc0c0c0, 167 | skyblue: 0x87ceeb, 168 | slateblue: 0x6a5acd, 169 | slategray: 0x708090, 170 | slategrey: 0x708090, 171 | snow: 0xfffafa, 172 | springgreen: 0x00ff7f, 173 | steelblue: 0x4682b4, 174 | tan: 0xd2b48c, 175 | teal: 0x008080, 176 | thistle: 0xd8bfd8, 177 | tomato: 0xff6347, 178 | turquoise: 0x40e0d0, 179 | violet: 0xee82ee, 180 | wheat: 0xf5deb3, 181 | white: 0xffffff, 182 | whitesmoke: 0xf5f5f5, 183 | yellow: 0xffff00, 184 | yellowgreen: 0x9acd32 185 | }; 186 | 187 | define(Color, color, { 188 | displayable: function() { 189 | return this.rgb().displayable(); 190 | }, 191 | toString: function() { 192 | return this.rgb() + ""; 193 | } 194 | }); 195 | 196 | function color(format) { 197 | var m; 198 | format = (format + "").trim().toLowerCase(); 199 | 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 200 | : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 201 | : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) 202 | : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) 203 | : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) 204 | : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) 205 | : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) 206 | : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) 207 | : named.hasOwnProperty(format) ? rgbn(named[format]) 208 | : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) 209 | : null; 210 | } 211 | 212 | function rgbn(n) { 213 | return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); 214 | } 215 | 216 | function rgba(r, g, b, a) { 217 | if (a <= 0) r = g = b = NaN; 218 | return new Rgb(r, g, b, a); 219 | } 220 | 221 | function rgbConvert(o) { 222 | if (!(o instanceof Color)) o = color(o); 223 | if (!o) return new Rgb; 224 | o = o.rgb(); 225 | return new Rgb(o.r, o.g, o.b, o.opacity); 226 | } 227 | 228 | function rgb(r, g, b, opacity) { 229 | return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); 230 | } 231 | 232 | function Rgb(r, g, b, opacity) { 233 | this.r = +r; 234 | this.g = +g; 235 | this.b = +b; 236 | this.opacity = +opacity; 237 | } 238 | 239 | define(Rgb, rgb, extend(Color, { 240 | brighter: function(k) { 241 | k = k == null ? brighter : Math.pow(brighter, k); 242 | return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); 243 | }, 244 | darker: function(k) { 245 | k = k == null ? darker : Math.pow(darker, k); 246 | return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); 247 | }, 248 | rgb: function() { 249 | return this; 250 | }, 251 | displayable: function() { 252 | return (0 <= this.r && this.r <= 255) 253 | && (0 <= this.g && this.g <= 255) 254 | && (0 <= this.b && this.b <= 255) 255 | && (0 <= this.opacity && this.opacity <= 1); 256 | }, 257 | toString: function() { 258 | var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); 259 | return (a === 1 ? "rgb(" : "rgba(") 260 | + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " 261 | + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " 262 | + Math.max(0, Math.min(255, Math.round(this.b) || 0)) 263 | + (a === 1 ? ")" : ", " + a + ")"); 264 | } 265 | })); 266 | 267 | function hsla(h, s, l, a) { 268 | if (a <= 0) h = s = l = NaN; 269 | else if (l <= 0 || l >= 1) h = s = NaN; 270 | else if (s <= 0) h = NaN; 271 | return new Hsl(h, s, l, a); 272 | } 273 | 274 | function hslConvert(o) { 275 | if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); 276 | if (!(o instanceof Color)) o = color(o); 277 | if (!o) return new Hsl; 278 | if (o instanceof Hsl) return o; 279 | o = o.rgb(); 280 | var r = o.r / 255, 281 | g = o.g / 255, 282 | b = o.b / 255, 283 | min = Math.min(r, g, b), 284 | max = Math.max(r, g, b), 285 | h = NaN, 286 | s = max - min, 287 | l = (max + min) / 2; 288 | if (s) { 289 | if (r === max) h = (g - b) / s + (g < b) * 6; 290 | else if (g === max) h = (b - r) / s + 2; 291 | else h = (r - g) / s + 4; 292 | s /= l < 0.5 ? max + min : 2 - max - min; 293 | h *= 60; 294 | } else { 295 | s = l > 0 && l < 1 ? 0 : h; 296 | } 297 | return new Hsl(h, s, l, o.opacity); 298 | } 299 | 300 | function hsl(h, s, l, opacity) { 301 | return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); 302 | } 303 | 304 | function Hsl(h, s, l, opacity) { 305 | this.h = +h; 306 | this.s = +s; 307 | this.l = +l; 308 | this.opacity = +opacity; 309 | } 310 | 311 | define(Hsl, hsl, extend(Color, { 312 | brighter: function(k) { 313 | k = k == null ? brighter : Math.pow(brighter, k); 314 | return new Hsl(this.h, this.s, this.l * k, this.opacity); 315 | }, 316 | darker: function(k) { 317 | k = k == null ? darker : Math.pow(darker, k); 318 | return new Hsl(this.h, this.s, this.l * k, this.opacity); 319 | }, 320 | rgb: function() { 321 | var h = this.h % 360 + (this.h < 0) * 360, 322 | s = isNaN(h) || isNaN(this.s) ? 0 : this.s, 323 | l = this.l, 324 | m2 = l + (l < 0.5 ? l : 1 - l) * s, 325 | m1 = 2 * l - m2; 326 | return new Rgb( 327 | hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), 328 | hsl2rgb(h, m1, m2), 329 | hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), 330 | this.opacity 331 | ); 332 | }, 333 | displayable: function() { 334 | return (0 <= this.s && this.s <= 1 || isNaN(this.s)) 335 | && (0 <= this.l && this.l <= 1) 336 | && (0 <= this.opacity && this.opacity <= 1); 337 | } 338 | })); 339 | 340 | /* From FvD 13.37, CSS Color Module Level 3 */ 341 | function hsl2rgb(h, m1, m2) { 342 | return (h < 60 ? m1 + (m2 - m1) * h / 60 343 | : h < 180 ? m2 344 | : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 345 | : m1) * 255; 346 | } 347 | 348 | var deg2rad = Math.PI / 180; 349 | var rad2deg = 180 / Math.PI; 350 | 351 | var Kn = 18; 352 | var Xn = 0.950470; 353 | var Yn = 1; 354 | var Zn = 1.088830; 355 | var t0 = 4 / 29; 356 | var t1 = 6 / 29; 357 | var t2 = 3 * t1 * t1; 358 | var t3 = t1 * t1 * t1; 359 | 360 | function labConvert(o) { 361 | if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); 362 | if (o instanceof Hcl) { 363 | var h = o.h * deg2rad; 364 | return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); 365 | } 366 | if (!(o instanceof Rgb)) o = rgbConvert(o); 367 | var b = rgb2xyz(o.r), 368 | a = rgb2xyz(o.g), 369 | l = rgb2xyz(o.b), 370 | x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), 371 | y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), 372 | z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); 373 | return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); 374 | } 375 | 376 | function lab(l, a, b, opacity) { 377 | return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); 378 | } 379 | 380 | function Lab(l, a, b, opacity) { 381 | this.l = +l; 382 | this.a = +a; 383 | this.b = +b; 384 | this.opacity = +opacity; 385 | } 386 | 387 | define(Lab, lab, extend(Color, { 388 | brighter: function(k) { 389 | return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); 390 | }, 391 | darker: function(k) { 392 | return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); 393 | }, 394 | rgb: function() { 395 | var y = (this.l + 16) / 116, 396 | x = isNaN(this.a) ? y : y + this.a / 500, 397 | z = isNaN(this.b) ? y : y - this.b / 200; 398 | y = Yn * lab2xyz(y); 399 | x = Xn * lab2xyz(x); 400 | z = Zn * lab2xyz(z); 401 | return new Rgb( 402 | xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB 403 | xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), 404 | xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), 405 | this.opacity 406 | ); 407 | } 408 | })); 409 | 410 | function xyz2lab(t) { 411 | return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; 412 | } 413 | 414 | function lab2xyz(t) { 415 | return t > t1 ? t * t * t : t2 * (t - t0); 416 | } 417 | 418 | function xyz2rgb(x) { 419 | return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); 420 | } 421 | 422 | function rgb2xyz(x) { 423 | return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); 424 | } 425 | 426 | function hclConvert(o) { 427 | if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); 428 | if (!(o instanceof Lab)) o = labConvert(o); 429 | var h = Math.atan2(o.b, o.a) * rad2deg; 430 | return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); 431 | } 432 | 433 | function hcl(h, c, l, opacity) { 434 | return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); 435 | } 436 | 437 | function Hcl(h, c, l, opacity) { 438 | this.h = +h; 439 | this.c = +c; 440 | this.l = +l; 441 | this.opacity = +opacity; 442 | } 443 | 444 | define(Hcl, hcl, extend(Color, { 445 | brighter: function(k) { 446 | return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); 447 | }, 448 | darker: function(k) { 449 | return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); 450 | }, 451 | rgb: function() { 452 | return labConvert(this).rgb(); 453 | } 454 | })); 455 | 456 | var A = -0.14861; 457 | var B = +1.78277; 458 | var C = -0.29227; 459 | var D = -0.90649; 460 | var E = +1.97294; 461 | var ED = E * D; 462 | var EB = E * B; 463 | var BC_DA = B * C - D * A; 464 | 465 | function cubehelixConvert(o) { 466 | if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); 467 | if (!(o instanceof Rgb)) o = rgbConvert(o); 468 | var r = o.r / 255, 469 | g = o.g / 255, 470 | b = o.b / 255, 471 | l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), 472 | bl = b - l, 473 | k = (E * (g - l) - C * bl) / D, 474 | s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 475 | h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; 476 | return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); 477 | } 478 | 479 | function cubehelix(h, s, l, opacity) { 480 | return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); 481 | } 482 | 483 | function Cubehelix(h, s, l, opacity) { 484 | this.h = +h; 485 | this.s = +s; 486 | this.l = +l; 487 | this.opacity = +opacity; 488 | } 489 | 490 | define(Cubehelix, cubehelix, extend(Color, { 491 | brighter: function(k) { 492 | k = k == null ? brighter : Math.pow(brighter, k); 493 | return new Cubehelix(this.h, this.s, this.l * k, this.opacity); 494 | }, 495 | darker: function(k) { 496 | k = k == null ? darker : Math.pow(darker, k); 497 | return new Cubehelix(this.h, this.s, this.l * k, this.opacity); 498 | }, 499 | rgb: function() { 500 | var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, 501 | l = +this.l, 502 | a = isNaN(this.s) ? 0 : this.s * l * (1 - l), 503 | cosh = Math.cos(h), 504 | sinh = Math.sin(h); 505 | return new Rgb( 506 | 255 * (l + a * (A * cosh + B * sinh)), 507 | 255 * (l + a * (C * cosh + D * sinh)), 508 | 255 * (l + a * (E * cosh)), 509 | this.opacity 510 | ); 511 | } 512 | })); 513 | 514 | exports.color = color; 515 | exports.rgb = rgb; 516 | exports.hsl = hsl; 517 | exports.lab = lab; 518 | exports.hcl = hcl; 519 | exports.cubehelix = cubehelix; 520 | 521 | Object.defineProperty(exports, '__esModule', { value: true }); 522 | 523 | }))); 524 | -------------------------------------------------------------------------------- /js/d3-contour@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-contour/ Version 1.2.0. Copyright 2018 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) : 4 | typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) : 5 | (factory((global.d3 = global.d3 || {}),global.d3)); 6 | }(this, (function (exports,d3Array) { 'use strict'; 7 | 8 | var array = Array.prototype; 9 | 10 | var slice = array.slice; 11 | 12 | var ascending = function(a, b) { 13 | return a - b; 14 | }; 15 | 16 | var area = function(ring) { 17 | var i = 0, n = ring.length, area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1]; 18 | while (++i < n) area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1]; 19 | return area; 20 | }; 21 | 22 | var constant = function(x) { 23 | return function() { 24 | return x; 25 | }; 26 | }; 27 | 28 | var contains = function(ring, hole) { 29 | var i = -1, n = hole.length, c; 30 | while (++i < n) if (c = ringContains(ring, hole[i])) return c; 31 | return 0; 32 | }; 33 | 34 | function ringContains(ring, point) { 35 | var x = point[0], y = point[1], contains = -1; 36 | for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) { 37 | var pi = ring[i], xi = pi[0], yi = pi[1], pj = ring[j], xj = pj[0], yj = pj[1]; 38 | if (segmentContains(pi, pj, point)) return 0; 39 | if (((yi > y) !== (yj > y)) && ((x < (xj - xi) * (y - yi) / (yj - yi) + xi))) contains = -contains; 40 | } 41 | return contains; 42 | } 43 | 44 | function segmentContains(a, b, c) { 45 | var i; return collinear(a, b, c) && within(a[i = +(a[0] === b[0])], c[i], b[i]); 46 | } 47 | 48 | function collinear(a, b, c) { 49 | return (b[0] - a[0]) * (c[1] - a[1]) === (c[0] - a[0]) * (b[1] - a[1]); 50 | } 51 | 52 | function within(p, q, r) { 53 | return p <= q && q <= r || r <= q && q <= p; 54 | } 55 | 56 | var noop = function() {}; 57 | 58 | var cases = [ 59 | [], 60 | [[[1.0, 1.5], [0.5, 1.0]]], 61 | [[[1.5, 1.0], [1.0, 1.5]]], 62 | [[[1.5, 1.0], [0.5, 1.0]]], 63 | [[[1.0, 0.5], [1.5, 1.0]]], 64 | [[[1.0, 1.5], [0.5, 1.0]], [[1.0, 0.5], [1.5, 1.0]]], 65 | [[[1.0, 0.5], [1.0, 1.5]]], 66 | [[[1.0, 0.5], [0.5, 1.0]]], 67 | [[[0.5, 1.0], [1.0, 0.5]]], 68 | [[[1.0, 1.5], [1.0, 0.5]]], 69 | [[[0.5, 1.0], [1.0, 0.5]], [[1.5, 1.0], [1.0, 1.5]]], 70 | [[[1.5, 1.0], [1.0, 0.5]]], 71 | [[[0.5, 1.0], [1.5, 1.0]]], 72 | [[[1.0, 1.5], [1.5, 1.0]]], 73 | [[[0.5, 1.0], [1.0, 1.5]]], 74 | [] 75 | ]; 76 | 77 | var contours = function() { 78 | var dx = 1, 79 | dy = 1, 80 | threshold = d3Array.thresholdSturges, 81 | smooth = smoothLinear; 82 | 83 | function contours(values) { 84 | var tz = threshold(values); 85 | 86 | // Convert number of thresholds into uniform thresholds. 87 | if (!Array.isArray(tz)) { 88 | var domain = d3Array.extent(values), start = domain[0], stop = domain[1]; 89 | tz = d3Array.tickStep(start, stop, tz); 90 | tz = d3Array.range(Math.floor(start / tz) * tz, Math.floor(stop / tz) * tz, tz); 91 | } else { 92 | tz = tz.slice().sort(ascending); 93 | } 94 | 95 | return tz.map(function(value) { 96 | return contour(values, value); 97 | }); 98 | } 99 | 100 | // Accumulate, smooth contour rings, assign holes to exterior rings. 101 | // Based on https://github.com/mbostock/shapefile/blob/v0.6.2/shp/polygon.js 102 | function contour(values, value) { 103 | var polygons = [], 104 | holes = []; 105 | 106 | isorings(values, value, function(ring) { 107 | smooth(ring, values, value); 108 | if (area(ring) > 0) polygons.push([ring]); 109 | else holes.push(ring); 110 | }); 111 | 112 | holes.forEach(function(hole) { 113 | for (var i = 0, n = polygons.length, polygon; i < n; ++i) { 114 | if (contains((polygon = polygons[i])[0], hole) !== -1) { 115 | polygon.push(hole); 116 | return; 117 | } 118 | } 119 | }); 120 | 121 | return { 122 | type: "MultiPolygon", 123 | value: value, 124 | coordinates: polygons 125 | }; 126 | } 127 | 128 | // Marching squares with isolines stitched into rings. 129 | // Based on https://github.com/topojson/topojson-client/blob/v3.0.0/src/stitch.js 130 | function isorings(values, value, callback) { 131 | var fragmentByStart = new Array, 132 | fragmentByEnd = new Array, 133 | x, y, t0, t1, t2, t3; 134 | 135 | // Special case for the first row (y = -1, t2 = t3 = 0). 136 | x = y = -1; 137 | t1 = values[0] >= value; 138 | cases[t1 << 1].forEach(stitch); 139 | while (++x < dx - 1) { 140 | t0 = t1, t1 = values[x + 1] >= value; 141 | cases[t0 | t1 << 1].forEach(stitch); 142 | } 143 | cases[t1 << 0].forEach(stitch); 144 | 145 | // General case for the intermediate rows. 146 | while (++y < dy - 1) { 147 | x = -1; 148 | t1 = values[y * dx + dx] >= value; 149 | t2 = values[y * dx] >= value; 150 | cases[t1 << 1 | t2 << 2].forEach(stitch); 151 | while (++x < dx - 1) { 152 | t0 = t1, t1 = values[y * dx + dx + x + 1] >= value; 153 | t3 = t2, t2 = values[y * dx + x + 1] >= value; 154 | cases[t0 | t1 << 1 | t2 << 2 | t3 << 3].forEach(stitch); 155 | } 156 | cases[t1 | t2 << 3].forEach(stitch); 157 | } 158 | 159 | // Special case for the last row (y = dy - 1, t0 = t1 = 0). 160 | x = -1; 161 | t2 = values[y * dx] >= value; 162 | cases[t2 << 2].forEach(stitch); 163 | while (++x < dx - 1) { 164 | t3 = t2, t2 = values[y * dx + x + 1] >= value; 165 | cases[t2 << 2 | t3 << 3].forEach(stitch); 166 | } 167 | cases[t2 << 3].forEach(stitch); 168 | 169 | function stitch(line) { 170 | var start = [line[0][0] + x, line[0][1] + y], 171 | end = [line[1][0] + x, line[1][1] + y], 172 | startIndex = index(start), 173 | endIndex = index(end), 174 | f, g; 175 | if (f = fragmentByEnd[startIndex]) { 176 | if (g = fragmentByStart[endIndex]) { 177 | delete fragmentByEnd[f.end]; 178 | delete fragmentByStart[g.start]; 179 | if (f === g) { 180 | f.ring.push(end); 181 | callback(f.ring); 182 | } else { 183 | fragmentByStart[f.start] = fragmentByEnd[g.end] = {start: f.start, end: g.end, ring: f.ring.concat(g.ring)}; 184 | } 185 | } else { 186 | delete fragmentByEnd[f.end]; 187 | f.ring.push(end); 188 | fragmentByEnd[f.end = endIndex] = f; 189 | } 190 | } else if (f = fragmentByStart[endIndex]) { 191 | if (g = fragmentByEnd[startIndex]) { 192 | delete fragmentByStart[f.start]; 193 | delete fragmentByEnd[g.end]; 194 | if (f === g) { 195 | f.ring.push(end); 196 | callback(f.ring); 197 | } else { 198 | fragmentByStart[g.start] = fragmentByEnd[f.end] = {start: g.start, end: f.end, ring: g.ring.concat(f.ring)}; 199 | } 200 | } else { 201 | delete fragmentByStart[f.start]; 202 | f.ring.unshift(start); 203 | fragmentByStart[f.start = startIndex] = f; 204 | } 205 | } else { 206 | fragmentByStart[startIndex] = fragmentByEnd[endIndex] = {start: startIndex, end: endIndex, ring: [start, end]}; 207 | } 208 | } 209 | } 210 | 211 | function index(point) { 212 | return point[0] * 2 + point[1] * (dx + 1) * 4; 213 | } 214 | 215 | function smoothLinear(ring, values, value) { 216 | ring.forEach(function(point) { 217 | var x = point[0], 218 | y = point[1], 219 | xt = x | 0, 220 | yt = y | 0, 221 | v0, 222 | v1 = values[yt * dx + xt]; 223 | if (x > 0 && x < dx && xt === x) { 224 | v0 = values[yt * dx + xt - 1]; 225 | point[0] = x + (value - v0) / (v1 - v0) - 0.5; 226 | } 227 | if (y > 0 && y < dy && yt === y) { 228 | v0 = values[(yt - 1) * dx + xt]; 229 | point[1] = y + (value - v0) / (v1 - v0) - 0.5; 230 | } 231 | }); 232 | } 233 | 234 | contours.contour = contour; 235 | 236 | contours.size = function(_) { 237 | if (!arguments.length) return [dx, dy]; 238 | var _0 = Math.ceil(_[0]), _1 = Math.ceil(_[1]); 239 | if (!(_0 > 0) || !(_1 > 0)) throw new Error("invalid size"); 240 | return dx = _0, dy = _1, contours; 241 | }; 242 | 243 | contours.thresholds = function(_) { 244 | return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), contours) : threshold; 245 | }; 246 | 247 | contours.smooth = function(_) { 248 | return arguments.length ? (smooth = _ ? smoothLinear : noop, contours) : smooth === smoothLinear; 249 | }; 250 | 251 | return contours; 252 | }; 253 | 254 | // TODO Optimize edge cases. 255 | // TODO Optimize index calculation. 256 | // TODO Optimize arguments. 257 | function blurX(source, target, r) { 258 | var n = source.width, 259 | m = source.height, 260 | w = (r << 1) + 1; 261 | for (var j = 0; j < m; ++j) { 262 | for (var i = 0, sr = 0; i < n + r; ++i) { 263 | if (i < n) { 264 | sr += source.data[i + j * n]; 265 | } 266 | if (i >= r) { 267 | if (i >= w) { 268 | sr -= source.data[i - w + j * n]; 269 | } 270 | target.data[i - r + j * n] = sr / Math.min(i + 1, n - 1 + w - i, w); 271 | } 272 | } 273 | } 274 | } 275 | 276 | // TODO Optimize edge cases. 277 | // TODO Optimize index calculation. 278 | // TODO Optimize arguments. 279 | function blurY(source, target, r) { 280 | var n = source.width, 281 | m = source.height, 282 | w = (r << 1) + 1; 283 | for (var i = 0; i < n; ++i) { 284 | for (var j = 0, sr = 0; j < m + r; ++j) { 285 | if (j < m) { 286 | sr += source.data[i + j * n]; 287 | } 288 | if (j >= r) { 289 | if (j >= w) { 290 | sr -= source.data[i + (j - w) * n]; 291 | } 292 | target.data[i + (j - r) * n] = sr / Math.min(j + 1, m - 1 + w - j, w); 293 | } 294 | } 295 | } 296 | } 297 | 298 | function defaultX(d) { 299 | return d[0]; 300 | } 301 | 302 | function defaultY(d) { 303 | return d[1]; 304 | } 305 | 306 | var density = function() { 307 | var x = defaultX, 308 | y = defaultY, 309 | dx = 960, 310 | dy = 500, 311 | r = 20, // blur radius 312 | k = 2, // log2(grid cell size) 313 | o = r * 3, // grid offset, to pad for blur 314 | n = (dx + o * 2) >> k, // grid width 315 | m = (dy + o * 2) >> k, // grid height 316 | threshold = constant(20); 317 | 318 | function density(data) { 319 | var values0 = new Float32Array(n * m), 320 | values1 = new Float32Array(n * m); 321 | 322 | data.forEach(function(d, i, data) { 323 | var xi = (x(d, i, data) + o) >> k, 324 | yi = (y(d, i, data) + o) >> k; 325 | if (xi >= 0 && xi < n && yi >= 0 && yi < m) { 326 | ++values0[xi + yi * n]; 327 | } 328 | }); 329 | 330 | // TODO Optimize. 331 | blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k); 332 | blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k); 333 | blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k); 334 | blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k); 335 | blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k); 336 | blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k); 337 | 338 | var tz = threshold(values0); 339 | 340 | // Convert number of thresholds into uniform thresholds. 341 | if (!Array.isArray(tz)) { 342 | var stop = d3Array.max(values0); 343 | tz = d3Array.tickStep(0, stop, tz); 344 | tz = d3Array.range(0, Math.floor(stop / tz) * tz, tz); 345 | tz.shift(); 346 | } 347 | 348 | return contours() 349 | .thresholds(tz) 350 | .size([n, m]) 351 | (values0) 352 | .map(transform); 353 | } 354 | 355 | function transform(geometry) { 356 | geometry.value *= Math.pow(2, -2 * k); // Density in points per square pixel. 357 | geometry.coordinates.forEach(transformPolygon); 358 | return geometry; 359 | } 360 | 361 | function transformPolygon(coordinates) { 362 | coordinates.forEach(transformRing); 363 | } 364 | 365 | function transformRing(coordinates) { 366 | coordinates.forEach(transformPoint); 367 | } 368 | 369 | // TODO Optimize. 370 | function transformPoint(coordinates) { 371 | coordinates[0] = coordinates[0] * Math.pow(2, k) - o; 372 | coordinates[1] = coordinates[1] * Math.pow(2, k) - o; 373 | } 374 | 375 | function resize() { 376 | o = r * 3; 377 | n = (dx + o * 2) >> k; 378 | m = (dy + o * 2) >> k; 379 | return density; 380 | } 381 | 382 | density.x = function(_) { 383 | return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), density) : x; 384 | }; 385 | 386 | density.y = function(_) { 387 | return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), density) : y; 388 | }; 389 | 390 | density.size = function(_) { 391 | if (!arguments.length) return [dx, dy]; 392 | var _0 = Math.ceil(_[0]), _1 = Math.ceil(_[1]); 393 | if (!(_0 >= 0) && !(_0 >= 0)) throw new Error("invalid size"); 394 | return dx = _0, dy = _1, resize(); 395 | }; 396 | 397 | density.cellSize = function(_) { 398 | if (!arguments.length) return 1 << k; 399 | if (!((_ = +_) >= 1)) throw new Error("invalid cell size"); 400 | return k = Math.floor(Math.log(_) / Math.LN2), resize(); 401 | }; 402 | 403 | density.thresholds = function(_) { 404 | return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), density) : threshold; 405 | }; 406 | 407 | density.bandwidth = function(_) { 408 | if (!arguments.length) return Math.sqrt(r * (r + 1)); 409 | if (!((_ = +_) >= 0)) throw new Error("invalid bandwidth"); 410 | return r = Math.round((Math.sqrt(4 * _ * _ + 1) - 1) / 2), resize(); 411 | }; 412 | 413 | return density; 414 | }; 415 | 416 | exports.contours = contours; 417 | exports.contourDensity = density; 418 | 419 | Object.defineProperty(exports, '__esModule', { value: true }); 420 | 421 | }))); 422 | -------------------------------------------------------------------------------- /js/d3-dispatch@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-dispatch/ Version 1.0.3. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 4 | typeof define === 'function' && define.amd ? define(['exports'], factory) : 5 | (factory((global.d3 = global.d3 || {}))); 6 | }(this, (function (exports) { 'use strict'; 7 | 8 | var noop = {value: function() {}}; 9 | 10 | function dispatch() { 11 | for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { 12 | if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); 13 | _[t] = []; 14 | } 15 | return new Dispatch(_); 16 | } 17 | 18 | function Dispatch(_) { 19 | this._ = _; 20 | } 21 | 22 | function parseTypenames(typenames, types) { 23 | return typenames.trim().split(/^|\s+/).map(function(t) { 24 | var name = "", i = t.indexOf("."); 25 | if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); 26 | if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); 27 | return {type: t, name: name}; 28 | }); 29 | } 30 | 31 | Dispatch.prototype = dispatch.prototype = { 32 | constructor: Dispatch, 33 | on: function(typename, callback) { 34 | var _ = this._, 35 | T = parseTypenames(typename + "", _), 36 | t, 37 | i = -1, 38 | n = T.length; 39 | 40 | // If no callback was specified, return the callback of the given type and name. 41 | if (arguments.length < 2) { 42 | while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; 43 | return; 44 | } 45 | 46 | // If a type was specified, set the callback for the given type and name. 47 | // Otherwise, if a null callback was specified, remove callbacks of the given name. 48 | if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); 49 | while (++i < n) { 50 | if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); 51 | else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); 52 | } 53 | 54 | return this; 55 | }, 56 | copy: function() { 57 | var copy = {}, _ = this._; 58 | for (var t in _) copy[t] = _[t].slice(); 59 | return new Dispatch(copy); 60 | }, 61 | call: function(type, that) { 62 | if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; 63 | if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); 64 | for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); 65 | }, 66 | apply: function(type, that, args) { 67 | if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); 68 | for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); 69 | } 70 | }; 71 | 72 | function get(type, name) { 73 | for (var i = 0, n = type.length, c; i < n; ++i) { 74 | if ((c = type[i]).name === name) { 75 | return c.value; 76 | } 77 | } 78 | } 79 | 80 | function set(type, name, callback) { 81 | for (var i = 0, n = type.length; i < n; ++i) { 82 | if (type[i].name === name) { 83 | type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); 84 | break; 85 | } 86 | } 87 | if (callback != null) type.push({name: name, value: callback}); 88 | return type; 89 | } 90 | 91 | exports.dispatch = dispatch; 92 | 93 | Object.defineProperty(exports, '__esModule', { value: true }); 94 | 95 | }))); 96 | -------------------------------------------------------------------------------- /js/d3-drag@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-drag/ Version 1.2.1. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-selection')) : 4 | typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-selection'], factory) : 5 | (factory((global.d3 = global.d3 || {}),global.d3,global.d3)); 6 | }(this, (function (exports,d3Dispatch,d3Selection) { 'use strict'; 7 | 8 | function nopropagation() { 9 | d3Selection.event.stopImmediatePropagation(); 10 | } 11 | 12 | var noevent = function() { 13 | d3Selection.event.preventDefault(); 14 | d3Selection.event.stopImmediatePropagation(); 15 | }; 16 | 17 | var nodrag = function(view) { 18 | var root = view.document.documentElement, 19 | selection = d3Selection.select(view).on("dragstart.drag", noevent, true); 20 | if ("onselectstart" in root) { 21 | selection.on("selectstart.drag", noevent, true); 22 | } else { 23 | root.__noselect = root.style.MozUserSelect; 24 | root.style.MozUserSelect = "none"; 25 | } 26 | }; 27 | 28 | function yesdrag(view, noclick) { 29 | var root = view.document.documentElement, 30 | selection = d3Selection.select(view).on("dragstart.drag", null); 31 | if (noclick) { 32 | selection.on("click.drag", noevent, true); 33 | setTimeout(function() { selection.on("click.drag", null); }, 0); 34 | } 35 | if ("onselectstart" in root) { 36 | selection.on("selectstart.drag", null); 37 | } else { 38 | root.style.MozUserSelect = root.__noselect; 39 | delete root.__noselect; 40 | } 41 | } 42 | 43 | var constant = function(x) { 44 | return function() { 45 | return x; 46 | }; 47 | }; 48 | 49 | function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch$$1) { 50 | this.target = target; 51 | this.type = type; 52 | this.subject = subject; 53 | this.identifier = id; 54 | this.active = active; 55 | this.x = x; 56 | this.y = y; 57 | this.dx = dx; 58 | this.dy = dy; 59 | this._ = dispatch$$1; 60 | } 61 | 62 | DragEvent.prototype.on = function() { 63 | var value = this._.on.apply(this._, arguments); 64 | return value === this._ ? this : value; 65 | }; 66 | 67 | // Ignore right-click, since that should open the context menu. 68 | function defaultFilter() { 69 | return !d3Selection.event.button; 70 | } 71 | 72 | function defaultContainer() { 73 | return this.parentNode; 74 | } 75 | 76 | function defaultSubject(d) { 77 | return d == null ? {x: d3Selection.event.x, y: d3Selection.event.y} : d; 78 | } 79 | 80 | function defaultTouchable() { 81 | return "ontouchstart" in this; 82 | } 83 | 84 | var drag = function() { 85 | var filter = defaultFilter, 86 | container = defaultContainer, 87 | subject = defaultSubject, 88 | touchable = defaultTouchable, 89 | gestures = {}, 90 | listeners = d3Dispatch.dispatch("start", "drag", "end"), 91 | active = 0, 92 | mousedownx, 93 | mousedowny, 94 | mousemoving, 95 | touchending, 96 | clickDistance2 = 0; 97 | 98 | function drag(selection) { 99 | selection 100 | .on("mousedown.drag", mousedowned) 101 | .filter(touchable) 102 | .on("touchstart.drag", touchstarted) 103 | .on("touchmove.drag", touchmoved) 104 | .on("touchend.drag touchcancel.drag", touchended) 105 | .style("touch-action", "none") 106 | .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); 107 | } 108 | 109 | function mousedowned() { 110 | if (touchending || !filter.apply(this, arguments)) return; 111 | var gesture = beforestart("mouse", container.apply(this, arguments), d3Selection.mouse, this, arguments); 112 | if (!gesture) return; 113 | d3Selection.select(d3Selection.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); 114 | nodrag(d3Selection.event.view); 115 | nopropagation(); 116 | mousemoving = false; 117 | mousedownx = d3Selection.event.clientX; 118 | mousedowny = d3Selection.event.clientY; 119 | gesture("start"); 120 | } 121 | 122 | function mousemoved() { 123 | noevent(); 124 | if (!mousemoving) { 125 | var dx = d3Selection.event.clientX - mousedownx, dy = d3Selection.event.clientY - mousedowny; 126 | mousemoving = dx * dx + dy * dy > clickDistance2; 127 | } 128 | gestures.mouse("drag"); 129 | } 130 | 131 | function mouseupped() { 132 | d3Selection.select(d3Selection.event.view).on("mousemove.drag mouseup.drag", null); 133 | yesdrag(d3Selection.event.view, mousemoving); 134 | noevent(); 135 | gestures.mouse("end"); 136 | } 137 | 138 | function touchstarted() { 139 | if (!filter.apply(this, arguments)) return; 140 | var touches = d3Selection.event.changedTouches, 141 | c = container.apply(this, arguments), 142 | n = touches.length, i, gesture; 143 | 144 | for (i = 0; i < n; ++i) { 145 | if (gesture = beforestart(touches[i].identifier, c, d3Selection.touch, this, arguments)) { 146 | nopropagation(); 147 | gesture("start"); 148 | } 149 | } 150 | } 151 | 152 | function touchmoved() { 153 | var touches = d3Selection.event.changedTouches, 154 | n = touches.length, i, gesture; 155 | 156 | for (i = 0; i < n; ++i) { 157 | if (gesture = gestures[touches[i].identifier]) { 158 | noevent(); 159 | gesture("drag"); 160 | } 161 | } 162 | } 163 | 164 | function touchended() { 165 | var touches = d3Selection.event.changedTouches, 166 | n = touches.length, i, gesture; 167 | 168 | if (touchending) clearTimeout(touchending); 169 | touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! 170 | for (i = 0; i < n; ++i) { 171 | if (gesture = gestures[touches[i].identifier]) { 172 | nopropagation(); 173 | gesture("end"); 174 | } 175 | } 176 | } 177 | 178 | function beforestart(id, container, point, that, args) { 179 | var p = point(container, id), s, dx, dy, 180 | sublisteners = listeners.copy(); 181 | 182 | if (!d3Selection.customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { 183 | if ((d3Selection.event.subject = s = subject.apply(that, args)) == null) return false; 184 | dx = s.x - p[0] || 0; 185 | dy = s.y - p[1] || 0; 186 | return true; 187 | })) return; 188 | 189 | return function gesture(type) { 190 | var p0 = p, n; 191 | switch (type) { 192 | case "start": gestures[id] = gesture, n = active++; break; 193 | case "end": delete gestures[id], --active; // nobreak 194 | case "drag": p = point(container, id), n = active; break; 195 | } 196 | d3Selection.customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); 197 | }; 198 | } 199 | 200 | drag.filter = function(_) { 201 | return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter; 202 | }; 203 | 204 | drag.container = function(_) { 205 | return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container; 206 | }; 207 | 208 | drag.subject = function(_) { 209 | return arguments.length ? (subject = typeof _ === "function" ? _ : constant(_), drag) : subject; 210 | }; 211 | 212 | drag.touchable = function(_) { 213 | return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), drag) : touchable; 214 | }; 215 | 216 | drag.on = function() { 217 | var value = listeners.on.apply(listeners, arguments); 218 | return value === listeners ? drag : value; 219 | }; 220 | 221 | drag.clickDistance = function(_) { 222 | return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); 223 | }; 224 | 225 | return drag; 226 | }; 227 | 228 | exports.drag = drag; 229 | exports.dragDisable = nodrag; 230 | exports.dragEnable = yesdrag; 231 | 232 | Object.defineProperty(exports, '__esModule', { value: true }); 233 | 234 | }))); 235 | -------------------------------------------------------------------------------- /js/d3-interpolate@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-interpolate/ Version 1.1.6. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-color')) : 4 | typeof define === 'function' && define.amd ? define(['exports', 'd3-color'], factory) : 5 | (factory((global.d3 = global.d3 || {}),global.d3)); 6 | }(this, (function (exports,d3Color) { 'use strict'; 7 | 8 | function basis(t1, v0, v1, v2, v3) { 9 | var t2 = t1 * t1, t3 = t2 * t1; 10 | return ((1 - 3 * t1 + 3 * t2 - t3) * v0 11 | + (4 - 6 * t2 + 3 * t3) * v1 12 | + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 13 | + t3 * v3) / 6; 14 | } 15 | 16 | var basis$1 = function(values) { 17 | var n = values.length - 1; 18 | return function(t) { 19 | var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), 20 | v1 = values[i], 21 | v2 = values[i + 1], 22 | v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, 23 | v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; 24 | return basis((t - i / n) * n, v0, v1, v2, v3); 25 | }; 26 | }; 27 | 28 | var basisClosed = function(values) { 29 | var n = values.length; 30 | return function(t) { 31 | var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), 32 | v0 = values[(i + n - 1) % n], 33 | v1 = values[i % n], 34 | v2 = values[(i + 1) % n], 35 | v3 = values[(i + 2) % n]; 36 | return basis((t - i / n) * n, v0, v1, v2, v3); 37 | }; 38 | }; 39 | 40 | var constant = function(x) { 41 | return function() { 42 | return x; 43 | }; 44 | }; 45 | 46 | function linear(a, d) { 47 | return function(t) { 48 | return a + t * d; 49 | }; 50 | } 51 | 52 | function exponential(a, b, y) { 53 | return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { 54 | return Math.pow(a + t * b, y); 55 | }; 56 | } 57 | 58 | function hue(a, b) { 59 | var d = b - a; 60 | return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a); 61 | } 62 | 63 | function gamma(y) { 64 | return (y = +y) === 1 ? nogamma : function(a, b) { 65 | return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a); 66 | }; 67 | } 68 | 69 | function nogamma(a, b) { 70 | var d = b - a; 71 | return d ? linear(a, d) : constant(isNaN(a) ? b : a); 72 | } 73 | 74 | var rgb$1 = ((function rgbGamma(y) { 75 | var color$$1 = gamma(y); 76 | 77 | function rgb$$1(start, end) { 78 | var r = color$$1((start = d3Color.rgb(start)).r, (end = d3Color.rgb(end)).r), 79 | g = color$$1(start.g, end.g), 80 | b = color$$1(start.b, end.b), 81 | opacity = nogamma(start.opacity, end.opacity); 82 | return function(t) { 83 | start.r = r(t); 84 | start.g = g(t); 85 | start.b = b(t); 86 | start.opacity = opacity(t); 87 | return start + ""; 88 | }; 89 | } 90 | 91 | rgb$$1.gamma = rgbGamma; 92 | 93 | return rgb$$1; 94 | }))(1); 95 | 96 | function rgbSpline(spline) { 97 | return function(colors) { 98 | var n = colors.length, 99 | r = new Array(n), 100 | g = new Array(n), 101 | b = new Array(n), 102 | i, color$$1; 103 | for (i = 0; i < n; ++i) { 104 | color$$1 = d3Color.rgb(colors[i]); 105 | r[i] = color$$1.r || 0; 106 | g[i] = color$$1.g || 0; 107 | b[i] = color$$1.b || 0; 108 | } 109 | r = spline(r); 110 | g = spline(g); 111 | b = spline(b); 112 | color$$1.opacity = 1; 113 | return function(t) { 114 | color$$1.r = r(t); 115 | color$$1.g = g(t); 116 | color$$1.b = b(t); 117 | return color$$1 + ""; 118 | }; 119 | }; 120 | } 121 | 122 | var rgbBasis = rgbSpline(basis$1); 123 | var rgbBasisClosed = rgbSpline(basisClosed); 124 | 125 | var array = function(a, b) { 126 | var nb = b ? b.length : 0, 127 | na = a ? Math.min(nb, a.length) : 0, 128 | x = new Array(na), 129 | c = new Array(nb), 130 | i; 131 | 132 | for (i = 0; i < na; ++i) x[i] = value(a[i], b[i]); 133 | for (; i < nb; ++i) c[i] = b[i]; 134 | 135 | return function(t) { 136 | for (i = 0; i < na; ++i) c[i] = x[i](t); 137 | return c; 138 | }; 139 | }; 140 | 141 | var date = function(a, b) { 142 | var d = new Date; 143 | return a = +a, b -= a, function(t) { 144 | return d.setTime(a + b * t), d; 145 | }; 146 | }; 147 | 148 | var number = function(a, b) { 149 | return a = +a, b -= a, function(t) { 150 | return a + b * t; 151 | }; 152 | }; 153 | 154 | var object = function(a, b) { 155 | var i = {}, 156 | c = {}, 157 | k; 158 | 159 | if (a === null || typeof a !== "object") a = {}; 160 | if (b === null || typeof b !== "object") b = {}; 161 | 162 | for (k in b) { 163 | if (k in a) { 164 | i[k] = value(a[k], b[k]); 165 | } else { 166 | c[k] = b[k]; 167 | } 168 | } 169 | 170 | return function(t) { 171 | for (k in i) c[k] = i[k](t); 172 | return c; 173 | }; 174 | }; 175 | 176 | var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; 177 | var reB = new RegExp(reA.source, "g"); 178 | 179 | function zero(b) { 180 | return function() { 181 | return b; 182 | }; 183 | } 184 | 185 | function one(b) { 186 | return function(t) { 187 | return b(t) + ""; 188 | }; 189 | } 190 | 191 | var string = function(a, b) { 192 | var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b 193 | am, // current match in a 194 | bm, // current match in b 195 | bs, // string preceding current number in b, if any 196 | i = -1, // index in s 197 | s = [], // string constants and placeholders 198 | q = []; // number interpolators 199 | 200 | // Coerce inputs to strings. 201 | a = a + "", b = b + ""; 202 | 203 | // Interpolate pairs of numbers in a & b. 204 | while ((am = reA.exec(a)) 205 | && (bm = reB.exec(b))) { 206 | if ((bs = bm.index) > bi) { // a string precedes the next number in b 207 | bs = b.slice(bi, bs); 208 | if (s[i]) s[i] += bs; // coalesce with previous string 209 | else s[++i] = bs; 210 | } 211 | if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match 212 | if (s[i]) s[i] += bm; // coalesce with previous string 213 | else s[++i] = bm; 214 | } else { // interpolate non-matching numbers 215 | s[++i] = null; 216 | q.push({i: i, x: number(am, bm)}); 217 | } 218 | bi = reB.lastIndex; 219 | } 220 | 221 | // Add remains of b. 222 | if (bi < b.length) { 223 | bs = b.slice(bi); 224 | if (s[i]) s[i] += bs; // coalesce with previous string 225 | else s[++i] = bs; 226 | } 227 | 228 | // Special optimization for only a single match. 229 | // Otherwise, interpolate each of the numbers and rejoin the string. 230 | return s.length < 2 ? (q[0] 231 | ? one(q[0].x) 232 | : zero(b)) 233 | : (b = q.length, function(t) { 234 | for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); 235 | return s.join(""); 236 | }); 237 | }; 238 | 239 | var value = function(a, b) { 240 | var t = typeof b, c; 241 | return b == null || t === "boolean" ? constant(b) 242 | : (t === "number" ? number 243 | : t === "string" ? ((c = d3Color.color(b)) ? (b = c, rgb$1) : string) 244 | : b instanceof d3Color.color ? rgb$1 245 | : b instanceof Date ? date 246 | : Array.isArray(b) ? array 247 | : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object 248 | : number)(a, b); 249 | }; 250 | 251 | var round = function(a, b) { 252 | return a = +a, b -= a, function(t) { 253 | return Math.round(a + b * t); 254 | }; 255 | }; 256 | 257 | var degrees = 180 / Math.PI; 258 | 259 | var identity = { 260 | translateX: 0, 261 | translateY: 0, 262 | rotate: 0, 263 | skewX: 0, 264 | scaleX: 1, 265 | scaleY: 1 266 | }; 267 | 268 | var decompose = function(a, b, c, d, e, f) { 269 | var scaleX, scaleY, skewX; 270 | if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; 271 | if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; 272 | if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; 273 | if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; 274 | return { 275 | translateX: e, 276 | translateY: f, 277 | rotate: Math.atan2(b, a) * degrees, 278 | skewX: Math.atan(skewX) * degrees, 279 | scaleX: scaleX, 280 | scaleY: scaleY 281 | }; 282 | }; 283 | 284 | var cssNode; 285 | var cssRoot; 286 | var cssView; 287 | var svgNode; 288 | 289 | function parseCss(value) { 290 | if (value === "none") return identity; 291 | if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; 292 | cssNode.style.transform = value; 293 | value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); 294 | cssRoot.removeChild(cssNode); 295 | value = value.slice(7, -1).split(","); 296 | return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); 297 | } 298 | 299 | function parseSvg(value) { 300 | if (value == null) return identity; 301 | if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); 302 | svgNode.setAttribute("transform", value); 303 | if (!(value = svgNode.transform.baseVal.consolidate())) return identity; 304 | value = value.matrix; 305 | return decompose(value.a, value.b, value.c, value.d, value.e, value.f); 306 | } 307 | 308 | function interpolateTransform(parse, pxComma, pxParen, degParen) { 309 | 310 | function pop(s) { 311 | return s.length ? s.pop() + " " : ""; 312 | } 313 | 314 | function translate(xa, ya, xb, yb, s, q) { 315 | if (xa !== xb || ya !== yb) { 316 | var i = s.push("translate(", null, pxComma, null, pxParen); 317 | q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); 318 | } else if (xb || yb) { 319 | s.push("translate(" + xb + pxComma + yb + pxParen); 320 | } 321 | } 322 | 323 | function rotate(a, b, s, q) { 324 | if (a !== b) { 325 | if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path 326 | q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number(a, b)}); 327 | } else if (b) { 328 | s.push(pop(s) + "rotate(" + b + degParen); 329 | } 330 | } 331 | 332 | function skewX(a, b, s, q) { 333 | if (a !== b) { 334 | q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(a, b)}); 335 | } else if (b) { 336 | s.push(pop(s) + "skewX(" + b + degParen); 337 | } 338 | } 339 | 340 | function scale(xa, ya, xb, yb, s, q) { 341 | if (xa !== xb || ya !== yb) { 342 | var i = s.push(pop(s) + "scale(", null, ",", null, ")"); 343 | q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); 344 | } else if (xb !== 1 || yb !== 1) { 345 | s.push(pop(s) + "scale(" + xb + "," + yb + ")"); 346 | } 347 | } 348 | 349 | return function(a, b) { 350 | var s = [], // string constants and placeholders 351 | q = []; // number interpolators 352 | a = parse(a), b = parse(b); 353 | translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); 354 | rotate(a.rotate, b.rotate, s, q); 355 | skewX(a.skewX, b.skewX, s, q); 356 | scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); 357 | a = b = null; // gc 358 | return function(t) { 359 | var i = -1, n = q.length, o; 360 | while (++i < n) s[(o = q[i]).i] = o.x(t); 361 | return s.join(""); 362 | }; 363 | }; 364 | } 365 | 366 | var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); 367 | var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); 368 | 369 | var rho = Math.SQRT2; 370 | var rho2 = 2; 371 | var rho4 = 4; 372 | var epsilon2 = 1e-12; 373 | 374 | function cosh(x) { 375 | return ((x = Math.exp(x)) + 1 / x) / 2; 376 | } 377 | 378 | function sinh(x) { 379 | return ((x = Math.exp(x)) - 1 / x) / 2; 380 | } 381 | 382 | function tanh(x) { 383 | return ((x = Math.exp(2 * x)) - 1) / (x + 1); 384 | } 385 | 386 | // p0 = [ux0, uy0, w0] 387 | // p1 = [ux1, uy1, w1] 388 | var zoom = function(p0, p1) { 389 | var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], 390 | ux1 = p1[0], uy1 = p1[1], w1 = p1[2], 391 | dx = ux1 - ux0, 392 | dy = uy1 - uy0, 393 | d2 = dx * dx + dy * dy, 394 | i, 395 | S; 396 | 397 | // Special case for u0 ≅ u1. 398 | if (d2 < epsilon2) { 399 | S = Math.log(w1 / w0) / rho; 400 | i = function(t) { 401 | return [ 402 | ux0 + t * dx, 403 | uy0 + t * dy, 404 | w0 * Math.exp(rho * t * S) 405 | ]; 406 | }; 407 | } 408 | 409 | // General case. 410 | else { 411 | var d1 = Math.sqrt(d2), 412 | b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), 413 | b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), 414 | r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), 415 | r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); 416 | S = (r1 - r0) / rho; 417 | i = function(t) { 418 | var s = t * S, 419 | coshr0 = cosh(r0), 420 | u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); 421 | return [ 422 | ux0 + u * dx, 423 | uy0 + u * dy, 424 | w0 * coshr0 / cosh(rho * s + r0) 425 | ]; 426 | }; 427 | } 428 | 429 | i.duration = S * 1000; 430 | 431 | return i; 432 | }; 433 | 434 | function hsl$1(hue$$1) { 435 | return function(start, end) { 436 | var h = hue$$1((start = d3Color.hsl(start)).h, (end = d3Color.hsl(end)).h), 437 | s = nogamma(start.s, end.s), 438 | l = nogamma(start.l, end.l), 439 | opacity = nogamma(start.opacity, end.opacity); 440 | return function(t) { 441 | start.h = h(t); 442 | start.s = s(t); 443 | start.l = l(t); 444 | start.opacity = opacity(t); 445 | return start + ""; 446 | }; 447 | } 448 | } 449 | 450 | var hsl$2 = hsl$1(hue); 451 | var hslLong = hsl$1(nogamma); 452 | 453 | function lab$1(start, end) { 454 | var l = nogamma((start = d3Color.lab(start)).l, (end = d3Color.lab(end)).l), 455 | a = nogamma(start.a, end.a), 456 | b = nogamma(start.b, end.b), 457 | opacity = nogamma(start.opacity, end.opacity); 458 | return function(t) { 459 | start.l = l(t); 460 | start.a = a(t); 461 | start.b = b(t); 462 | start.opacity = opacity(t); 463 | return start + ""; 464 | }; 465 | } 466 | 467 | function hcl$1(hue$$1) { 468 | return function(start, end) { 469 | var h = hue$$1((start = d3Color.hcl(start)).h, (end = d3Color.hcl(end)).h), 470 | c = nogamma(start.c, end.c), 471 | l = nogamma(start.l, end.l), 472 | opacity = nogamma(start.opacity, end.opacity); 473 | return function(t) { 474 | start.h = h(t); 475 | start.c = c(t); 476 | start.l = l(t); 477 | start.opacity = opacity(t); 478 | return start + ""; 479 | }; 480 | } 481 | } 482 | 483 | var hcl$2 = hcl$1(hue); 484 | var hclLong = hcl$1(nogamma); 485 | 486 | function cubehelix$1(hue$$1) { 487 | return (function cubehelixGamma(y) { 488 | y = +y; 489 | 490 | function cubehelix$$1(start, end) { 491 | var h = hue$$1((start = d3Color.cubehelix(start)).h, (end = d3Color.cubehelix(end)).h), 492 | s = nogamma(start.s, end.s), 493 | l = nogamma(start.l, end.l), 494 | opacity = nogamma(start.opacity, end.opacity); 495 | return function(t) { 496 | start.h = h(t); 497 | start.s = s(t); 498 | start.l = l(Math.pow(t, y)); 499 | start.opacity = opacity(t); 500 | return start + ""; 501 | }; 502 | } 503 | 504 | cubehelix$$1.gamma = cubehelixGamma; 505 | 506 | return cubehelix$$1; 507 | })(1); 508 | } 509 | 510 | var cubehelix$2 = cubehelix$1(hue); 511 | var cubehelixLong = cubehelix$1(nogamma); 512 | 513 | var quantize = function(interpolator, n) { 514 | var samples = new Array(n); 515 | for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); 516 | return samples; 517 | }; 518 | 519 | exports.interpolate = value; 520 | exports.interpolateArray = array; 521 | exports.interpolateBasis = basis$1; 522 | exports.interpolateBasisClosed = basisClosed; 523 | exports.interpolateDate = date; 524 | exports.interpolateNumber = number; 525 | exports.interpolateObject = object; 526 | exports.interpolateRound = round; 527 | exports.interpolateString = string; 528 | exports.interpolateTransformCss = interpolateTransformCss; 529 | exports.interpolateTransformSvg = interpolateTransformSvg; 530 | exports.interpolateZoom = zoom; 531 | exports.interpolateRgb = rgb$1; 532 | exports.interpolateRgbBasis = rgbBasis; 533 | exports.interpolateRgbBasisClosed = rgbBasisClosed; 534 | exports.interpolateHsl = hsl$2; 535 | exports.interpolateHslLong = hslLong; 536 | exports.interpolateLab = lab$1; 537 | exports.interpolateHcl = hcl$2; 538 | exports.interpolateHclLong = hclLong; 539 | exports.interpolateCubehelix = cubehelix$2; 540 | exports.interpolateCubehelixLong = cubehelixLong; 541 | exports.quantize = quantize; 542 | 543 | Object.defineProperty(exports, '__esModule', { value: true }); 544 | 545 | }))); 546 | -------------------------------------------------------------------------------- /js/d3-request@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-request/ Version 1.0.6. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-collection'), require('d3-dispatch'), require('d3-dsv')) : 4 | typeof define === 'function' && define.amd ? define(['exports', 'd3-collection', 'd3-dispatch', 'd3-dsv'], factory) : 5 | (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3)); 6 | }(this, (function (exports,d3Collection,d3Dispatch,d3Dsv) { 'use strict'; 7 | 8 | var request = function(url, callback) { 9 | var request, 10 | event = d3Dispatch.dispatch("beforesend", "progress", "load", "error"), 11 | mimeType, 12 | headers = d3Collection.map(), 13 | xhr = new XMLHttpRequest, 14 | user = null, 15 | password = null, 16 | response, 17 | responseType, 18 | timeout = 0; 19 | 20 | // If IE does not support CORS, use XDomainRequest. 21 | if (typeof XDomainRequest !== "undefined" 22 | && !("withCredentials" in xhr) 23 | && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; 24 | 25 | "onload" in xhr 26 | ? xhr.onload = xhr.onerror = xhr.ontimeout = respond 27 | : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; 28 | 29 | function respond(o) { 30 | var status = xhr.status, result; 31 | if (!status && hasResponse(xhr) 32 | || status >= 200 && status < 300 33 | || status === 304) { 34 | if (response) { 35 | try { 36 | result = response.call(request, xhr); 37 | } catch (e) { 38 | event.call("error", request, e); 39 | return; 40 | } 41 | } else { 42 | result = xhr; 43 | } 44 | event.call("load", request, result); 45 | } else { 46 | event.call("error", request, o); 47 | } 48 | } 49 | 50 | xhr.onprogress = function(e) { 51 | event.call("progress", request, e); 52 | }; 53 | 54 | request = { 55 | header: function(name, value) { 56 | name = (name + "").toLowerCase(); 57 | if (arguments.length < 2) return headers.get(name); 58 | if (value == null) headers.remove(name); 59 | else headers.set(name, value + ""); 60 | return request; 61 | }, 62 | 63 | // If mimeType is non-null and no Accept header is set, a default is used. 64 | mimeType: function(value) { 65 | if (!arguments.length) return mimeType; 66 | mimeType = value == null ? null : value + ""; 67 | return request; 68 | }, 69 | 70 | // Specifies what type the response value should take; 71 | // for instance, arraybuffer, blob, document, or text. 72 | responseType: function(value) { 73 | if (!arguments.length) return responseType; 74 | responseType = value; 75 | return request; 76 | }, 77 | 78 | timeout: function(value) { 79 | if (!arguments.length) return timeout; 80 | timeout = +value; 81 | return request; 82 | }, 83 | 84 | user: function(value) { 85 | return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); 86 | }, 87 | 88 | password: function(value) { 89 | return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); 90 | }, 91 | 92 | // Specify how to convert the response content to a specific type; 93 | // changes the callback value on "load" events. 94 | response: function(value) { 95 | response = value; 96 | return request; 97 | }, 98 | 99 | // Alias for send("GET", …). 100 | get: function(data, callback) { 101 | return request.send("GET", data, callback); 102 | }, 103 | 104 | // Alias for send("POST", …). 105 | post: function(data, callback) { 106 | return request.send("POST", data, callback); 107 | }, 108 | 109 | // If callback is non-null, it will be used for error and load events. 110 | send: function(method, data, callback) { 111 | xhr.open(method, url, true, user, password); 112 | if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); 113 | if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); 114 | if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); 115 | if (responseType != null) xhr.responseType = responseType; 116 | if (timeout > 0) xhr.timeout = timeout; 117 | if (callback == null && typeof data === "function") callback = data, data = null; 118 | if (callback != null && callback.length === 1) callback = fixCallback(callback); 119 | if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); 120 | event.call("beforesend", request, xhr); 121 | xhr.send(data == null ? null : data); 122 | return request; 123 | }, 124 | 125 | abort: function() { 126 | xhr.abort(); 127 | return request; 128 | }, 129 | 130 | on: function() { 131 | var value = event.on.apply(event, arguments); 132 | return value === event ? request : value; 133 | } 134 | }; 135 | 136 | if (callback != null) { 137 | if (typeof callback !== "function") throw new Error("invalid callback: " + callback); 138 | return request.get(callback); 139 | } 140 | 141 | return request; 142 | }; 143 | 144 | function fixCallback(callback) { 145 | return function(error, xhr) { 146 | callback(error == null ? xhr : null); 147 | }; 148 | } 149 | 150 | function hasResponse(xhr) { 151 | var type = xhr.responseType; 152 | return type && type !== "text" 153 | ? xhr.response // null on error 154 | : xhr.responseText; // "" on error 155 | } 156 | 157 | var type = function(defaultMimeType, response) { 158 | return function(url, callback) { 159 | var r = request(url).mimeType(defaultMimeType).response(response); 160 | if (callback != null) { 161 | if (typeof callback !== "function") throw new Error("invalid callback: " + callback); 162 | return r.get(callback); 163 | } 164 | return r; 165 | }; 166 | }; 167 | 168 | var html = type("text/html", function(xhr) { 169 | return document.createRange().createContextualFragment(xhr.responseText); 170 | }); 171 | 172 | var json = type("application/json", function(xhr) { 173 | return JSON.parse(xhr.responseText); 174 | }); 175 | 176 | var text = type("text/plain", function(xhr) { 177 | return xhr.responseText; 178 | }); 179 | 180 | var xml = type("application/xml", function(xhr) { 181 | var xml = xhr.responseXML; 182 | if (!xml) throw new Error("parse error"); 183 | return xml; 184 | }); 185 | 186 | var dsv = function(defaultMimeType, parse) { 187 | return function(url, row, callback) { 188 | if (arguments.length < 3) callback = row, row = null; 189 | var r = request(url).mimeType(defaultMimeType); 190 | r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; 191 | r.row(row); 192 | return callback ? r.get(callback) : r; 193 | }; 194 | }; 195 | 196 | function responseOf(parse, row) { 197 | return function(request$$1) { 198 | return parse(request$$1.responseText, row); 199 | }; 200 | } 201 | 202 | var csv = dsv("text/csv", d3Dsv.csvParse); 203 | 204 | var tsv = dsv("text/tab-separated-values", d3Dsv.tsvParse); 205 | 206 | exports.request = request; 207 | exports.html = html; 208 | exports.json = json; 209 | exports.text = text; 210 | exports.xml = xml; 211 | exports.csv = csv; 212 | exports.tsv = tsv; 213 | 214 | Object.defineProperty(exports, '__esModule', { value: true }); 215 | 216 | }))); 217 | -------------------------------------------------------------------------------- /js/d3-zoom@1: -------------------------------------------------------------------------------- 1 | // https://d3js.org/d3-zoom/ Version 1.7.1. Copyright 2017 Mike Bostock. 2 | (function (global, factory) { 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-drag'), require('d3-interpolate'), require('d3-selection'), require('d3-transition')) : 4 | typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-drag', 'd3-interpolate', 'd3-selection', 'd3-transition'], factory) : 5 | (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3)); 6 | }(this, (function (exports,d3Dispatch,d3Drag,d3Interpolate,d3Selection,d3Transition) { 'use strict'; 7 | 8 | var constant = function(x) { 9 | return function() { 10 | return x; 11 | }; 12 | }; 13 | 14 | function ZoomEvent(target, type, transform) { 15 | this.target = target; 16 | this.type = type; 17 | this.transform = transform; 18 | } 19 | 20 | function Transform(k, x, y) { 21 | this.k = k; 22 | this.x = x; 23 | this.y = y; 24 | } 25 | 26 | Transform.prototype = { 27 | constructor: Transform, 28 | scale: function(k) { 29 | return k === 1 ? this : new Transform(this.k * k, this.x, this.y); 30 | }, 31 | translate: function(x, y) { 32 | return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); 33 | }, 34 | apply: function(point) { 35 | return [point[0] * this.k + this.x, point[1] * this.k + this.y]; 36 | }, 37 | applyX: function(x) { 38 | return x * this.k + this.x; 39 | }, 40 | applyY: function(y) { 41 | return y * this.k + this.y; 42 | }, 43 | invert: function(location) { 44 | return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; 45 | }, 46 | invertX: function(x) { 47 | return (x - this.x) / this.k; 48 | }, 49 | invertY: function(y) { 50 | return (y - this.y) / this.k; 51 | }, 52 | rescaleX: function(x) { 53 | return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); 54 | }, 55 | rescaleY: function(y) { 56 | return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); 57 | }, 58 | toString: function() { 59 | return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; 60 | } 61 | }; 62 | 63 | var identity = new Transform(1, 0, 0); 64 | 65 | transform.prototype = Transform.prototype; 66 | 67 | function transform(node) { 68 | return node.__zoom || identity; 69 | } 70 | 71 | function nopropagation() { 72 | d3Selection.event.stopImmediatePropagation(); 73 | } 74 | 75 | var noevent = function() { 76 | d3Selection.event.preventDefault(); 77 | d3Selection.event.stopImmediatePropagation(); 78 | }; 79 | 80 | // Ignore right-click, since that should open the context menu. 81 | function defaultFilter() { 82 | return !d3Selection.event.button; 83 | } 84 | 85 | function defaultExtent() { 86 | var e = this, w, h; 87 | if (e instanceof SVGElement) { 88 | e = e.ownerSVGElement || e; 89 | w = e.width.baseVal.value; 90 | h = e.height.baseVal.value; 91 | } else { 92 | w = e.clientWidth; 93 | h = e.clientHeight; 94 | } 95 | return [[0, 0], [w, h]]; 96 | } 97 | 98 | function defaultTransform() { 99 | return this.__zoom || identity; 100 | } 101 | 102 | function defaultWheelDelta() { 103 | return -d3Selection.event.deltaY * (d3Selection.event.deltaMode ? 120 : 1) / 500; 104 | } 105 | 106 | function defaultTouchable() { 107 | return "ontouchstart" in this; 108 | } 109 | 110 | function defaultConstrain(transform$$1, extent, translateExtent) { 111 | var dx0 = transform$$1.invertX(extent[0][0]) - translateExtent[0][0], 112 | dx1 = transform$$1.invertX(extent[1][0]) - translateExtent[1][0], 113 | dy0 = transform$$1.invertY(extent[0][1]) - translateExtent[0][1], 114 | dy1 = transform$$1.invertY(extent[1][1]) - translateExtent[1][1]; 115 | return transform$$1.translate( 116 | dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), 117 | dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) 118 | ); 119 | } 120 | 121 | var zoom = function() { 122 | var filter = defaultFilter, 123 | extent = defaultExtent, 124 | constrain = defaultConstrain, 125 | wheelDelta = defaultWheelDelta, 126 | touchable = defaultTouchable, 127 | scaleExtent = [0, Infinity], 128 | translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], 129 | duration = 250, 130 | interpolate = d3Interpolate.interpolateZoom, 131 | gestures = [], 132 | listeners = d3Dispatch.dispatch("start", "zoom", "end"), 133 | touchstarting, 134 | touchending, 135 | touchDelay = 500, 136 | wheelDelay = 150, 137 | clickDistance2 = 0; 138 | 139 | function zoom(selection) { 140 | selection 141 | .property("__zoom", defaultTransform) 142 | .on("wheel.zoom", wheeled) 143 | .on("mousedown.zoom", mousedowned) 144 | .on("dblclick.zoom", dblclicked) 145 | .filter(touchable) 146 | .on("touchstart.zoom", touchstarted) 147 | .on("touchmove.zoom", touchmoved) 148 | .on("touchend.zoom touchcancel.zoom", touchended) 149 | .style("touch-action", "none") 150 | .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); 151 | } 152 | 153 | zoom.transform = function(collection, transform$$1) { 154 | var selection = collection.selection ? collection.selection() : collection; 155 | selection.property("__zoom", defaultTransform); 156 | if (collection !== selection) { 157 | schedule(collection, transform$$1); 158 | } else { 159 | selection.interrupt().each(function() { 160 | gesture(this, arguments) 161 | .start() 162 | .zoom(null, typeof transform$$1 === "function" ? transform$$1.apply(this, arguments) : transform$$1) 163 | .end(); 164 | }); 165 | } 166 | }; 167 | 168 | zoom.scaleBy = function(selection, k) { 169 | zoom.scaleTo(selection, function() { 170 | var k0 = this.__zoom.k, 171 | k1 = typeof k === "function" ? k.apply(this, arguments) : k; 172 | return k0 * k1; 173 | }); 174 | }; 175 | 176 | zoom.scaleTo = function(selection, k) { 177 | zoom.transform(selection, function() { 178 | var e = extent.apply(this, arguments), 179 | t0 = this.__zoom, 180 | p0 = centroid(e), 181 | p1 = t0.invert(p0), 182 | k1 = typeof k === "function" ? k.apply(this, arguments) : k; 183 | return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent); 184 | }); 185 | }; 186 | 187 | zoom.translateBy = function(selection, x, y) { 188 | zoom.transform(selection, function() { 189 | return constrain(this.__zoom.translate( 190 | typeof x === "function" ? x.apply(this, arguments) : x, 191 | typeof y === "function" ? y.apply(this, arguments) : y 192 | ), extent.apply(this, arguments), translateExtent); 193 | }); 194 | }; 195 | 196 | zoom.translateTo = function(selection, x, y) { 197 | zoom.transform(selection, function() { 198 | var e = extent.apply(this, arguments), 199 | t = this.__zoom, 200 | p = centroid(e); 201 | return constrain(identity.translate(p[0], p[1]).scale(t.k).translate( 202 | typeof x === "function" ? -x.apply(this, arguments) : -x, 203 | typeof y === "function" ? -y.apply(this, arguments) : -y 204 | ), e, translateExtent); 205 | }); 206 | }; 207 | 208 | function scale(transform$$1, k) { 209 | k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k)); 210 | return k === transform$$1.k ? transform$$1 : new Transform(k, transform$$1.x, transform$$1.y); 211 | } 212 | 213 | function translate(transform$$1, p0, p1) { 214 | var x = p0[0] - p1[0] * transform$$1.k, y = p0[1] - p1[1] * transform$$1.k; 215 | return x === transform$$1.x && y === transform$$1.y ? transform$$1 : new Transform(transform$$1.k, x, y); 216 | } 217 | 218 | function centroid(extent) { 219 | return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; 220 | } 221 | 222 | function schedule(transition, transform$$1, center) { 223 | transition 224 | .on("start.zoom", function() { gesture(this, arguments).start(); }) 225 | .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); }) 226 | .tween("zoom", function() { 227 | var that = this, 228 | args = arguments, 229 | g = gesture(that, args), 230 | e = extent.apply(that, args), 231 | p = center || centroid(e), 232 | w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), 233 | a = that.__zoom, 234 | b = typeof transform$$1 === "function" ? transform$$1.apply(that, args) : transform$$1, 235 | i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); 236 | return function(t) { 237 | if (t === 1) t = b; // Avoid rounding error on end. 238 | else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } 239 | g.zoom(null, t); 240 | }; 241 | }); 242 | } 243 | 244 | function gesture(that, args) { 245 | for (var i = 0, n = gestures.length, g; i < n; ++i) { 246 | if ((g = gestures[i]).that === that) { 247 | return g; 248 | } 249 | } 250 | return new Gesture(that, args); 251 | } 252 | 253 | function Gesture(that, args) { 254 | this.that = that; 255 | this.args = args; 256 | this.index = -1; 257 | this.active = 0; 258 | this.extent = extent.apply(that, args); 259 | } 260 | 261 | Gesture.prototype = { 262 | start: function() { 263 | if (++this.active === 1) { 264 | this.index = gestures.push(this) - 1; 265 | this.emit("start"); 266 | } 267 | return this; 268 | }, 269 | zoom: function(key, transform$$1) { 270 | if (this.mouse && key !== "mouse") this.mouse[1] = transform$$1.invert(this.mouse[0]); 271 | if (this.touch0 && key !== "touch") this.touch0[1] = transform$$1.invert(this.touch0[0]); 272 | if (this.touch1 && key !== "touch") this.touch1[1] = transform$$1.invert(this.touch1[0]); 273 | this.that.__zoom = transform$$1; 274 | this.emit("zoom"); 275 | return this; 276 | }, 277 | end: function() { 278 | if (--this.active === 0) { 279 | gestures.splice(this.index, 1); 280 | this.index = -1; 281 | this.emit("end"); 282 | } 283 | return this; 284 | }, 285 | emit: function(type) { 286 | d3Selection.customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); 287 | } 288 | }; 289 | 290 | function wheeled() { 291 | if (!filter.apply(this, arguments)) return; 292 | var g = gesture(this, arguments), 293 | t = this.__zoom, 294 | k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), 295 | p = d3Selection.mouse(this); 296 | 297 | // If the mouse is in the same location as before, reuse it. 298 | // If there were recent wheel events, reset the wheel idle timeout. 299 | if (g.wheel) { 300 | if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { 301 | g.mouse[1] = t.invert(g.mouse[0] = p); 302 | } 303 | clearTimeout(g.wheel); 304 | } 305 | 306 | // If this wheel event won’t trigger a transform change, ignore it. 307 | else if (t.k === k) return; 308 | 309 | // Otherwise, capture the mouse point and location at the start. 310 | else { 311 | g.mouse = [p, t.invert(p)]; 312 | d3Transition.interrupt(this); 313 | g.start(); 314 | } 315 | 316 | noevent(); 317 | g.wheel = setTimeout(wheelidled, wheelDelay); 318 | g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent)); 319 | 320 | function wheelidled() { 321 | g.wheel = null; 322 | g.end(); 323 | } 324 | } 325 | 326 | function mousedowned() { 327 | if (touchending || !filter.apply(this, arguments)) return; 328 | var g = gesture(this, arguments), 329 | v = d3Selection.select(d3Selection.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), 330 | p = d3Selection.mouse(this), 331 | x0 = d3Selection.event.clientX, 332 | y0 = d3Selection.event.clientY; 333 | 334 | d3Drag.dragDisable(d3Selection.event.view); 335 | nopropagation(); 336 | g.mouse = [p, this.__zoom.invert(p)]; 337 | d3Transition.interrupt(this); 338 | g.start(); 339 | 340 | function mousemoved() { 341 | noevent(); 342 | if (!g.moved) { 343 | var dx = d3Selection.event.clientX - x0, dy = d3Selection.event.clientY - y0; 344 | g.moved = dx * dx + dy * dy > clickDistance2; 345 | } 346 | g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = d3Selection.mouse(g.that), g.mouse[1]), g.extent, translateExtent)); 347 | } 348 | 349 | function mouseupped() { 350 | v.on("mousemove.zoom mouseup.zoom", null); 351 | d3Drag.dragEnable(d3Selection.event.view, g.moved); 352 | noevent(); 353 | g.end(); 354 | } 355 | } 356 | 357 | function dblclicked() { 358 | if (!filter.apply(this, arguments)) return; 359 | var t0 = this.__zoom, 360 | p0 = d3Selection.mouse(this), 361 | p1 = t0.invert(p0), 362 | k1 = t0.k * (d3Selection.event.shiftKey ? 0.5 : 2), 363 | t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments), translateExtent); 364 | 365 | noevent(); 366 | if (duration > 0) d3Selection.select(this).transition().duration(duration).call(schedule, t1, p0); 367 | else d3Selection.select(this).call(zoom.transform, t1); 368 | } 369 | 370 | function touchstarted() { 371 | if (!filter.apply(this, arguments)) return; 372 | var g = gesture(this, arguments), 373 | touches = d3Selection.event.changedTouches, 374 | started, 375 | n = touches.length, i, t, p; 376 | 377 | nopropagation(); 378 | for (i = 0; i < n; ++i) { 379 | t = touches[i], p = d3Selection.touch(this, touches, t.identifier); 380 | p = [p, this.__zoom.invert(p), t.identifier]; 381 | if (!g.touch0) g.touch0 = p, started = true; 382 | else if (!g.touch1) g.touch1 = p; 383 | } 384 | 385 | // If this is a dbltap, reroute to the (optional) dblclick.zoom handler. 386 | if (touchstarting) { 387 | touchstarting = clearTimeout(touchstarting); 388 | if (!g.touch1) { 389 | g.end(); 390 | p = d3Selection.select(this).on("dblclick.zoom"); 391 | if (p) p.apply(this, arguments); 392 | return; 393 | } 394 | } 395 | 396 | if (started) { 397 | touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); 398 | d3Transition.interrupt(this); 399 | g.start(); 400 | } 401 | } 402 | 403 | function touchmoved() { 404 | var g = gesture(this, arguments), 405 | touches = d3Selection.event.changedTouches, 406 | n = touches.length, i, t, p, l; 407 | 408 | noevent(); 409 | if (touchstarting) touchstarting = clearTimeout(touchstarting); 410 | for (i = 0; i < n; ++i) { 411 | t = touches[i], p = d3Selection.touch(this, touches, t.identifier); 412 | if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; 413 | else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; 414 | } 415 | t = g.that.__zoom; 416 | if (g.touch1) { 417 | var p0 = g.touch0[0], l0 = g.touch0[1], 418 | p1 = g.touch1[0], l1 = g.touch1[1], 419 | dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, 420 | dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; 421 | t = scale(t, Math.sqrt(dp / dl)); 422 | p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; 423 | l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; 424 | } 425 | else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; 426 | else return; 427 | g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent)); 428 | } 429 | 430 | function touchended() { 431 | var g = gesture(this, arguments), 432 | touches = d3Selection.event.changedTouches, 433 | n = touches.length, i, t; 434 | 435 | nopropagation(); 436 | if (touchending) clearTimeout(touchending); 437 | touchending = setTimeout(function() { touchending = null; }, touchDelay); 438 | for (i = 0; i < n; ++i) { 439 | t = touches[i]; 440 | if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; 441 | else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; 442 | } 443 | if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; 444 | if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]); 445 | else g.end(); 446 | } 447 | 448 | zoom.wheelDelta = function(_) { 449 | return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant(+_), zoom) : wheelDelta; 450 | }; 451 | 452 | zoom.filter = function(_) { 453 | return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), zoom) : filter; 454 | }; 455 | 456 | zoom.touchable = function(_) { 457 | return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), zoom) : touchable; 458 | }; 459 | 460 | zoom.extent = function(_) { 461 | return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; 462 | }; 463 | 464 | zoom.scaleExtent = function(_) { 465 | return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]]; 466 | }; 467 | 468 | zoom.translateExtent = function(_) { 469 | return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]]; 470 | }; 471 | 472 | zoom.constrain = function(_) { 473 | return arguments.length ? (constrain = _, zoom) : constrain; 474 | }; 475 | 476 | zoom.duration = function(_) { 477 | return arguments.length ? (duration = +_, zoom) : duration; 478 | }; 479 | 480 | zoom.interpolate = function(_) { 481 | return arguments.length ? (interpolate = _, zoom) : interpolate; 482 | }; 483 | 484 | zoom.on = function() { 485 | var value = listeners.on.apply(listeners, arguments); 486 | return value === listeners ? zoom : value; 487 | }; 488 | 489 | zoom.clickDistance = function(_) { 490 | return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2); 491 | }; 492 | 493 | return zoom; 494 | }; 495 | 496 | exports.zoom = zoom; 497 | exports.zoomTransform = transform; 498 | exports.zoomIdentity = identity; 499 | 500 | Object.defineProperty(exports, '__esModule', { value: true }); 501 | 502 | }))); 503 | -------------------------------------------------------------------------------- /js/topojson@1: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 3 | typeof define === 'function' && define.amd ? define(['exports'], factory) : 4 | (factory((global.topojson = global.topojson || {}))); 5 | }(this, (function (exports) { 'use strict'; 6 | 7 | function noop() {} 8 | 9 | function transformAbsolute(transform) { 10 | if (!transform) return noop; 11 | var x0, 12 | y0, 13 | kx = transform.scale[0], 14 | ky = transform.scale[1], 15 | dx = transform.translate[0], 16 | dy = transform.translate[1]; 17 | return function(point, i) { 18 | if (!i) x0 = y0 = 0; 19 | point[0] = (x0 += point[0]) * kx + dx; 20 | point[1] = (y0 += point[1]) * ky + dy; 21 | }; 22 | } 23 | 24 | function transformRelative(transform) { 25 | if (!transform) return noop; 26 | var x0, 27 | y0, 28 | kx = transform.scale[0], 29 | ky = transform.scale[1], 30 | dx = transform.translate[0], 31 | dy = transform.translate[1]; 32 | return function(point, i) { 33 | if (!i) x0 = y0 = 0; 34 | var x1 = Math.round((point[0] - dx) / kx), 35 | y1 = Math.round((point[1] - dy) / ky); 36 | point[0] = x1 - x0; 37 | point[1] = y1 - y0; 38 | x0 = x1; 39 | y0 = y1; 40 | }; 41 | } 42 | 43 | function reverse(array, n) { 44 | var t, j = array.length, i = j - n; 45 | while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; 46 | } 47 | 48 | function bisect(a, x) { 49 | var lo = 0, hi = a.length; 50 | while (lo < hi) { 51 | var mid = lo + hi >>> 1; 52 | if (a[mid] < x) lo = mid + 1; 53 | else hi = mid; 54 | } 55 | return lo; 56 | } 57 | 58 | function feature(topology, o) { 59 | return o.type === "GeometryCollection" ? { 60 | type: "FeatureCollection", 61 | features: o.geometries.map(function(o) { return feature$1(topology, o); }) 62 | } : feature$1(topology, o); 63 | } 64 | 65 | function feature$1(topology, o) { 66 | var f = { 67 | type: "Feature", 68 | id: o.id, 69 | properties: o.properties || {}, 70 | geometry: object(topology, o) 71 | }; 72 | if (o.id == null) delete f.id; 73 | return f; 74 | } 75 | 76 | function object(topology, o) { 77 | var absolute = transformAbsolute(topology.transform), 78 | arcs = topology.arcs; 79 | 80 | function arc(i, points) { 81 | if (points.length) points.pop(); 82 | for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) { 83 | points.push(p = a[k].slice()); 84 | absolute(p, k); 85 | } 86 | if (i < 0) reverse(points, n); 87 | } 88 | 89 | function point(p) { 90 | p = p.slice(); 91 | absolute(p, 0); 92 | return p; 93 | } 94 | 95 | function line(arcs) { 96 | var points = []; 97 | for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); 98 | if (points.length < 2) points.push(points[0].slice()); 99 | return points; 100 | } 101 | 102 | function ring(arcs) { 103 | var points = line(arcs); 104 | while (points.length < 4) points.push(points[0].slice()); 105 | return points; 106 | } 107 | 108 | function polygon(arcs) { 109 | return arcs.map(ring); 110 | } 111 | 112 | function geometry(o) { 113 | var t = o.type; 114 | return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)} 115 | : t in geometryType ? {type: t, coordinates: geometryType[t](o)} 116 | : null; 117 | } 118 | 119 | var geometryType = { 120 | Point: function(o) { return point(o.coordinates); }, 121 | MultiPoint: function(o) { return o.coordinates.map(point); }, 122 | LineString: function(o) { return line(o.arcs); }, 123 | MultiLineString: function(o) { return o.arcs.map(line); }, 124 | Polygon: function(o) { return polygon(o.arcs); }, 125 | MultiPolygon: function(o) { return o.arcs.map(polygon); } 126 | }; 127 | 128 | return geometry(o); 129 | } 130 | 131 | function stitchArcs(topology, arcs) { 132 | var stitchedArcs = {}, 133 | fragmentByStart = {}, 134 | fragmentByEnd = {}, 135 | fragments = [], 136 | emptyIndex = -1; 137 | 138 | // Stitch empty arcs first, since they may be subsumed by other arcs. 139 | arcs.forEach(function(i, j) { 140 | var arc = topology.arcs[i < 0 ? ~i : i], t; 141 | if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { 142 | t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; 143 | } 144 | }); 145 | 146 | arcs.forEach(function(i) { 147 | var e = ends(i), 148 | start = e[0], 149 | end = e[1], 150 | f, g; 151 | 152 | if (f = fragmentByEnd[start]) { 153 | delete fragmentByEnd[f.end]; 154 | f.push(i); 155 | f.end = end; 156 | if (g = fragmentByStart[end]) { 157 | delete fragmentByStart[g.start]; 158 | var fg = g === f ? f : f.concat(g); 159 | fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; 160 | } else { 161 | fragmentByStart[f.start] = fragmentByEnd[f.end] = f; 162 | } 163 | } else if (f = fragmentByStart[end]) { 164 | delete fragmentByStart[f.start]; 165 | f.unshift(i); 166 | f.start = start; 167 | if (g = fragmentByEnd[start]) { 168 | delete fragmentByEnd[g.end]; 169 | var gf = g === f ? f : g.concat(f); 170 | fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; 171 | } else { 172 | fragmentByStart[f.start] = fragmentByEnd[f.end] = f; 173 | } 174 | } else { 175 | f = [i]; 176 | fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; 177 | } 178 | }); 179 | 180 | function ends(i) { 181 | var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; 182 | if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); 183 | else p1 = arc[arc.length - 1]; 184 | return i < 0 ? [p1, p0] : [p0, p1]; 185 | } 186 | 187 | function flush(fragmentByEnd, fragmentByStart) { 188 | for (var k in fragmentByEnd) { 189 | var f = fragmentByEnd[k]; 190 | delete fragmentByStart[f.start]; 191 | delete f.start; 192 | delete f.end; 193 | f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); 194 | fragments.push(f); 195 | } 196 | } 197 | 198 | flush(fragmentByEnd, fragmentByStart); 199 | flush(fragmentByStart, fragmentByEnd); 200 | arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); 201 | 202 | return fragments; 203 | } 204 | 205 | function mesh(topology) { 206 | return object(topology, meshArcs.apply(this, arguments)); 207 | } 208 | 209 | function meshArcs(topology, o, filter) { 210 | var arcs = []; 211 | 212 | function arc(i) { 213 | var j = i < 0 ? ~i : i; 214 | (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); 215 | } 216 | 217 | function line(arcs) { 218 | arcs.forEach(arc); 219 | } 220 | 221 | function polygon(arcs) { 222 | arcs.forEach(line); 223 | } 224 | 225 | function geometry(o) { 226 | if (o.type === "GeometryCollection") o.geometries.forEach(geometry); 227 | else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs); 228 | } 229 | 230 | if (arguments.length > 1) { 231 | var geomsByArc = [], 232 | geom; 233 | 234 | var geometryType = { 235 | LineString: line, 236 | MultiLineString: polygon, 237 | Polygon: polygon, 238 | MultiPolygon: function(arcs) { arcs.forEach(polygon); } 239 | }; 240 | 241 | geometry(o); 242 | 243 | geomsByArc.forEach(arguments.length < 3 244 | ? function(geoms) { arcs.push(geoms[0].i); } 245 | : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); 246 | } else { 247 | for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i); 248 | } 249 | 250 | return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)}; 251 | } 252 | 253 | function cartesianTriangleArea(triangle) { 254 | var a = triangle[0], b = triangle[1], c = triangle[2]; 255 | return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1])); 256 | } 257 | 258 | function ring(ring) { 259 | var i = -1, 260 | n = ring.length, 261 | a, 262 | b = ring[n - 1], 263 | area = 0; 264 | 265 | while (++i < n) { 266 | a = b; 267 | b = ring[i]; 268 | area += a[0] * b[1] - a[1] * b[0]; 269 | } 270 | 271 | return area / 2; 272 | } 273 | 274 | function merge(topology) { 275 | return object(topology, mergeArcs.apply(this, arguments)); 276 | } 277 | 278 | function mergeArcs(topology, objects) { 279 | var polygonsByArc = {}, 280 | polygons = [], 281 | components = []; 282 | 283 | objects.forEach(function(o) { 284 | if (o.type === "Polygon") register(o.arcs); 285 | else if (o.type === "MultiPolygon") o.arcs.forEach(register); 286 | }); 287 | 288 | function register(polygon) { 289 | polygon.forEach(function(ring$$) { 290 | ring$$.forEach(function(arc) { 291 | (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); 292 | }); 293 | }); 294 | polygons.push(polygon); 295 | } 296 | 297 | function area(ring$$) { 298 | return Math.abs(ring(object(topology, {type: "Polygon", arcs: [ring$$]}).coordinates[0])); 299 | } 300 | 301 | polygons.forEach(function(polygon) { 302 | if (!polygon._) { 303 | var component = [], 304 | neighbors = [polygon]; 305 | polygon._ = 1; 306 | components.push(component); 307 | while (polygon = neighbors.pop()) { 308 | component.push(polygon); 309 | polygon.forEach(function(ring$$) { 310 | ring$$.forEach(function(arc) { 311 | polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { 312 | if (!polygon._) { 313 | polygon._ = 1; 314 | neighbors.push(polygon); 315 | } 316 | }); 317 | }); 318 | }); 319 | } 320 | } 321 | }); 322 | 323 | polygons.forEach(function(polygon) { 324 | delete polygon._; 325 | }); 326 | 327 | return { 328 | type: "MultiPolygon", 329 | arcs: components.map(function(polygons) { 330 | var arcs = [], n; 331 | 332 | // Extract the exterior (unique) arcs. 333 | polygons.forEach(function(polygon) { 334 | polygon.forEach(function(ring$$) { 335 | ring$$.forEach(function(arc) { 336 | if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { 337 | arcs.push(arc); 338 | } 339 | }); 340 | }); 341 | }); 342 | 343 | // Stitch the arcs into one or more rings. 344 | arcs = stitchArcs(topology, arcs); 345 | 346 | // If more than one ring is returned, 347 | // at most one of these rings can be the exterior; 348 | // choose the one with the greatest absolute area. 349 | if ((n = arcs.length) > 1) { 350 | for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) { 351 | if ((ki = area(arcs[i])) > k) { 352 | t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki; 353 | } 354 | } 355 | } 356 | 357 | return arcs; 358 | }) 359 | }; 360 | } 361 | 362 | function neighbors(objects) { 363 | var indexesByArc = {}, // arc index -> array of object indexes 364 | neighbors = objects.map(function() { return []; }); 365 | 366 | function line(arcs, i) { 367 | arcs.forEach(function(a) { 368 | if (a < 0) a = ~a; 369 | var o = indexesByArc[a]; 370 | if (o) o.push(i); 371 | else indexesByArc[a] = [i]; 372 | }); 373 | } 374 | 375 | function polygon(arcs, i) { 376 | arcs.forEach(function(arc) { line(arc, i); }); 377 | } 378 | 379 | function geometry(o, i) { 380 | if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); 381 | else if (o.type in geometryType) geometryType[o.type](o.arcs, i); 382 | } 383 | 384 | var geometryType = { 385 | LineString: line, 386 | MultiLineString: polygon, 387 | Polygon: polygon, 388 | MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } 389 | }; 390 | 391 | objects.forEach(geometry); 392 | 393 | for (var i in indexesByArc) { 394 | for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { 395 | for (var k = j + 1; k < m; ++k) { 396 | var ij = indexes[j], ik = indexes[k], n; 397 | if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); 398 | if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); 399 | } 400 | } 401 | } 402 | 403 | return neighbors; 404 | } 405 | 406 | function compareArea(a, b) { 407 | return a[1][2] - b[1][2]; 408 | } 409 | 410 | function minAreaHeap() { 411 | var heap = {}, 412 | array = [], 413 | size = 0; 414 | 415 | heap.push = function(object) { 416 | up(array[object._ = size] = object, size++); 417 | return size; 418 | }; 419 | 420 | heap.pop = function() { 421 | if (size <= 0) return; 422 | var removed = array[0], object; 423 | if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0); 424 | return removed; 425 | }; 426 | 427 | heap.remove = function(removed) { 428 | var i = removed._, object; 429 | if (array[i] !== removed) return; // invalid request 430 | if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i); 431 | return i; 432 | }; 433 | 434 | function up(object, i) { 435 | while (i > 0) { 436 | var j = ((i + 1) >> 1) - 1, 437 | parent = array[j]; 438 | if (compareArea(object, parent) >= 0) break; 439 | array[parent._ = i] = parent; 440 | array[object._ = i = j] = object; 441 | } 442 | } 443 | 444 | function down(object, i) { 445 | while (true) { 446 | var r = (i + 1) << 1, 447 | l = r - 1, 448 | j = i, 449 | child = array[j]; 450 | if (l < size && compareArea(array[l], child) < 0) child = array[j = l]; 451 | if (r < size && compareArea(array[r], child) < 0) child = array[j = r]; 452 | if (j === i) break; 453 | array[child._ = i] = child; 454 | array[object._ = i = j] = object; 455 | } 456 | } 457 | 458 | return heap; 459 | } 460 | 461 | function presimplify(topology, triangleArea) { 462 | var absolute = transformAbsolute(topology.transform), 463 | relative = transformRelative(topology.transform), 464 | heap = minAreaHeap(); 465 | 466 | if (!triangleArea) triangleArea = cartesianTriangleArea; 467 | 468 | topology.arcs.forEach(function(arc) { 469 | var triangles = [], 470 | maxArea = 0, 471 | triangle, 472 | i, 473 | n, 474 | p; 475 | 476 | // To store each point’s effective area, we create a new array rather than 477 | // extending the passed-in point to workaround a Chrome/V8 bug (getting 478 | // stuck in smi mode). For midpoints, the initial effective area of 479 | // Infinity will be computed in the next step. 480 | for (i = 0, n = arc.length; i < n; ++i) { 481 | p = arc[i]; 482 | absolute(arc[i] = [p[0], p[1], Infinity], i); 483 | } 484 | 485 | for (i = 1, n = arc.length - 1; i < n; ++i) { 486 | triangle = arc.slice(i - 1, i + 2); 487 | triangle[1][2] = triangleArea(triangle); 488 | triangles.push(triangle); 489 | heap.push(triangle); 490 | } 491 | 492 | for (i = 0, n = triangles.length; i < n; ++i) { 493 | triangle = triangles[i]; 494 | triangle.previous = triangles[i - 1]; 495 | triangle.next = triangles[i + 1]; 496 | } 497 | 498 | while (triangle = heap.pop()) { 499 | var previous = triangle.previous, 500 | next = triangle.next; 501 | 502 | // If the area of the current point is less than that of the previous point 503 | // to be eliminated, use the latter's area instead. This ensures that the 504 | // current point cannot be eliminated without eliminating previously- 505 | // eliminated points. 506 | if (triangle[1][2] < maxArea) triangle[1][2] = maxArea; 507 | else maxArea = triangle[1][2]; 508 | 509 | if (previous) { 510 | previous.next = next; 511 | previous[2] = triangle[2]; 512 | update(previous); 513 | } 514 | 515 | if (next) { 516 | next.previous = previous; 517 | next[0] = triangle[0]; 518 | update(next); 519 | } 520 | } 521 | 522 | arc.forEach(relative); 523 | }); 524 | 525 | function update(triangle) { 526 | heap.remove(triangle); 527 | triangle[1][2] = triangleArea(triangle); 528 | heap.push(triangle); 529 | } 530 | 531 | return topology; 532 | } 533 | 534 | var version = "1.6.27"; 535 | 536 | exports.version = version; 537 | exports.mesh = mesh; 538 | exports.meshArcs = meshArcs; 539 | exports.merge = merge; 540 | exports.mergeArcs = mergeArcs; 541 | exports.feature = feature; 542 | exports.neighbors = neighbors; 543 | exports.presimplify = presimplify; 544 | 545 | Object.defineProperty(exports, '__esModule', { value: true }); 546 | 547 | }))); -------------------------------------------------------------------------------- /js/versor@0: -------------------------------------------------------------------------------- 1 | (function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):t.versor=n()})(this,function(){"use strict";function t(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}var n=Math.acos,r=Math.asin,e=Math.atan2,a=Math.cos,u=Math.max,i=Math.min,o=Math.PI,f=Math.sin,c=Math.sqrt,s=o/180,h=180/o,d=function(t){var n=t[0]/2*s,r=f(n),e=a(n),u=t[1]/2*s,i=f(u),o=a(u),c=t[2]/2*s,h=f(c),d=a(c);return[e*o*d+r*i*h,r*o*d-e*i*h,e*i*d+r*o*h,e*o*h-r*i*d]};return d.cartesian=function(t){var n=t[0]*s,r=t[1]*s,e=a(r);return[e*a(n),e*f(n),f(r)]},d.rotation=function(t){return[e(2*(t[0]*t[1]+t[2]*t[3]),1-2*(t[1]*t[1]+t[2]*t[2]))*h,r(u(-1,i(1,2*(t[0]*t[2]-t[3]*t[1]))))*h,e(2*(t[0]*t[3]+t[1]*t[2]),1-2*(t[2]*t[2]+t[3]*t[3]))*h]},d.delta=function(r,e,o){2==arguments.length&&(o=1);var s=function(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}(r,e),h=c(t(s,s));if(!h)return[1,0,0,0];var d=o*n(u(-1,i(1,t(r,e))))/2,M=f(d);return[a(d),s[2]/h*M,-s[1]/h*M,s[0]/h*M]},d.multiply=function(t,n){return[t[0]*n[0]-t[1]*n[1]-t[2]*n[2]-t[3]*n[3],t[0]*n[1]+t[1]*n[0]+t[2]*n[3]-t[3]*n[2],t[0]*n[2]-t[1]*n[3]+t[2]*n[0]+t[3]*n[1],t[0]*n[3]+t[1]*n[2]-t[2]*n[1]+t[3]*n[0]]},d}); -------------------------------------------------------------------------------- /myreadme: -------------------------------------------------------------------------------- 1 | 2 | #================================================================================= 3 | d3 js from http://unpkg.com/ 4 | 5 | netcdfjs from https://github.com/cheminfo-js/netcdfjs 6 | npm install netcdfjs 7 | ls ~/node_modules/netcdfjs/dist/netcdfjs.js 8 | 9 | numjs from https://www.npmjs.com/package/numjs 10 | bower install numjs 11 | ls ~/bower_components/numjs/dist/numjs.js 12 | 13 | #================================================================================= 14 | http://geoexamples.com/d3/2017/11/04/raster-file-formats.html#html-example-1 15 | 16 | https://www.npmjs.com/package/netcdfjs 17 | https://github.com/cheminfo-js/netcdfjs 18 | 19 | contours with d3.js 20 | http://bl.ocks.org/rveciana/de0bd586eafd7fcdfe29227ccbdcd511 21 | GeoTIFF Contours II 22 | https://bl.ocks.org/mbostock/83c0be21dba7602ee14982b020b12f51 23 | 24 | geoTIFF and leaflet 25 | https://github.com/GeoTIFF/georaster-layer-for-leaflet 26 | https://github.com/IHCantabria/Leaflet.CanvasLayer.Field 27 | https://github.com/stuartmatthews/leaflet-geotiff 28 | 29 | D3.geo : Spherical arcs rather than straight lines for parallels ? 30 | https://stackoverflow.com/questions/25415885/d3-geo-spherical-arcs-rather-than-straight-lines-for-parallels 31 | 32 | #================================================================================= 33 | Tested with firefox and google-chrome 34 | 35 | If CORS (Cross-Origin Resource Sharing) problem, use: 36 | google-chrome --disable-web-security --user-data-dir 37 | 38 | #================================================================================= 39 | netcdfjs_01.html 40 | --> reading temp.nc 41 | 42 | netcdfjs_02.html 43 | --> reading uwnd.nc 44 | 45 | netcdfjs_03.html 46 | --> reading etopo_2.nc and display a projection 47 | 48 | netcdfjs_04.html 49 | --> reading etopo60_2.nc and display a projection from menu 50 | 51 | netcdfjs_05.html 52 | --> reading uwnd_2.nc and display a projection from menu 53 | 54 | #================================================================================= 55 | Problems: 56 | * have to save netcdf files to -180:180 57 | do know how to shift properly from js ? 58 | * antemeridian isocontours are not correct with uwnd.nc 59 | * missing value like in temp.nc 60 | 61 | TODO: 62 | * button to read new file 63 | * problem with netcdfjs that allow only read all the dimension (have to be 64 | only (lat, lon) not (time, lat, lon) 65 | * synchroneous maps 66 | * click to define new center rather than sliders https://bl.ocks.org/mbostock/3795040 67 | interactive_orthographic_02.html 68 | * use of context https://bl.ocks.org/mbostock/3788999 69 | -------------------------------------------------------------------------------- /navy_winds_0.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/navy_winds_0.nc -------------------------------------------------------------------------------- /navy_winds_2.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/navy_winds_2.nc -------------------------------------------------------------------------------- /netcdfjs_01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /netcdfjs_02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /netcdfjs_03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /netcdfjs_04.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 81 | 82 | 267 | 268 | 269 | -------------------------------------------------------------------------------- /netcdfjs_05.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 81 | 82 | 339 | 340 | 341 | -------------------------------------------------------------------------------- /raster-pixels-page_01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /raster-pixels-page_02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /sfctmp.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/sfctmp.tiff -------------------------------------------------------------------------------- /synchronized_maps_00.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |

Synchronized maps 37 | 38 |

39 |

40 | 41 | 42 | 141 | 142 | -------------------------------------------------------------------------------- /synchronized_maps_01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |

Synchronized maps 37 | 38 |

39 |

40 |
41 |
42 | 43 | 44 | 149 | 150 | -------------------------------------------------------------------------------- /synchronized_maps_02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |

Synchronized maps 51 | 52 |

53 |

54 |
uwnd
55 |
56 |
57 |
vwnd
58 |
59 | 60 | 61 | 265 | 266 | -------------------------------------------------------------------------------- /synchronized_maps_03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |

Synchronized maps 65 | 66 |

67 |

68 |
uwnd
69 |
70 |
71 |
vwnd
72 |
73 | 74 |
75 |
76 | 77 | 81 | 82 | 387 | 388 | 389 | 390 | -------------------------------------------------------------------------------- /temp.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/temp.nc -------------------------------------------------------------------------------- /tz850.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/tz850.tiff -------------------------------------------------------------------------------- /uwnd.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/uwnd.nc -------------------------------------------------------------------------------- /uwnd.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PBrockmann/D3_netcdfjs/91db6c917b47ec3f49db051dbe535e72f75a14b8/uwnd.tiff --------------------------------------------------------------------------------