You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

435 lines
12 KiB

1 year ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. // https://d3js.org/d3-quadtree/ v1.0.5 Copyright 2018 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. function tree_add(d) {
  8. var x = +this._x.call(null, d),
  9. y = +this._y.call(null, d);
  10. return add(this.cover(x, y), x, y, d);
  11. }
  12. function add(tree, x, y, d) {
  13. if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
  14. var parent,
  15. node = tree._root,
  16. leaf = {data: d},
  17. x0 = tree._x0,
  18. y0 = tree._y0,
  19. x1 = tree._x1,
  20. y1 = tree._y1,
  21. xm,
  22. ym,
  23. xp,
  24. yp,
  25. right,
  26. bottom,
  27. i,
  28. j;
  29. // If the tree is empty, initialize the root as a leaf.
  30. if (!node) return tree._root = leaf, tree;
  31. // Find the existing leaf for the new point, or add it.
  32. while (node.length) {
  33. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  34. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  35. if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
  36. }
  37. // Is the new point is exactly coincident with the existing point?
  38. xp = +tree._x.call(null, node.data);
  39. yp = +tree._y.call(null, node.data);
  40. if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
  41. // Otherwise, split the leaf node until the old and new point are separated.
  42. do {
  43. parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
  44. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  45. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  46. } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
  47. return parent[j] = node, parent[i] = leaf, tree;
  48. }
  49. function addAll(data) {
  50. var d, i, n = data.length,
  51. x,
  52. y,
  53. xz = new Array(n),
  54. yz = new Array(n),
  55. x0 = Infinity,
  56. y0 = Infinity,
  57. x1 = -Infinity,
  58. y1 = -Infinity;
  59. // Compute the points and their extent.
  60. for (i = 0; i < n; ++i) {
  61. if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
  62. xz[i] = x;
  63. yz[i] = y;
  64. if (x < x0) x0 = x;
  65. if (x > x1) x1 = x;
  66. if (y < y0) y0 = y;
  67. if (y > y1) y1 = y;
  68. }
  69. // If there were no (valid) points, inherit the existing extent.
  70. if (x1 < x0) x0 = this._x0, x1 = this._x1;
  71. if (y1 < y0) y0 = this._y0, y1 = this._y1;
  72. // Expand the tree to cover the new points.
  73. this.cover(x0, y0).cover(x1, y1);
  74. // Add the new points.
  75. for (i = 0; i < n; ++i) {
  76. add(this, xz[i], yz[i], data[i]);
  77. }
  78. return this;
  79. }
  80. function tree_cover(x, y) {
  81. if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
  82. var x0 = this._x0,
  83. y0 = this._y0,
  84. x1 = this._x1,
  85. y1 = this._y1;
  86. // If the quadtree has no extent, initialize them.
  87. // Integer extent are necessary so that if we later double the extent,
  88. // the existing quadrant boundaries don’t change due to floating point error!
  89. if (isNaN(x0)) {
  90. x1 = (x0 = Math.floor(x)) + 1;
  91. y1 = (y0 = Math.floor(y)) + 1;
  92. }
  93. // Otherwise, double repeatedly to cover.
  94. else if (x0 > x || x > x1 || y0 > y || y > y1) {
  95. var z = x1 - x0,
  96. node = this._root,
  97. parent,
  98. i;
  99. switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
  100. case 0: {
  101. do parent = new Array(4), parent[i] = node, node = parent;
  102. while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
  103. break;
  104. }
  105. case 1: {
  106. do parent = new Array(4), parent[i] = node, node = parent;
  107. while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
  108. break;
  109. }
  110. case 2: {
  111. do parent = new Array(4), parent[i] = node, node = parent;
  112. while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
  113. break;
  114. }
  115. case 3: {
  116. do parent = new Array(4), parent[i] = node, node = parent;
  117. while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
  118. break;
  119. }
  120. }
  121. if (this._root && this._root.length) this._root = node;
  122. }
  123. // If the quadtree covers the point already, just return.
  124. else return this;
  125. this._x0 = x0;
  126. this._y0 = y0;
  127. this._x1 = x1;
  128. this._y1 = y1;
  129. return this;
  130. }
  131. function tree_data() {
  132. var data = [];
  133. this.visit(function(node) {
  134. if (!node.length) do data.push(node.data); while (node = node.next)
  135. });
  136. return data;
  137. }
  138. function tree_extent(_) {
  139. return arguments.length
  140. ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
  141. : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
  142. }
  143. function Quad(node, x0, y0, x1, y1) {
  144. this.node = node;
  145. this.x0 = x0;
  146. this.y0 = y0;
  147. this.x1 = x1;
  148. this.y1 = y1;
  149. }
  150. function tree_find(x, y, radius) {
  151. var data,
  152. x0 = this._x0,
  153. y0 = this._y0,
  154. x1,
  155. y1,
  156. x2,
  157. y2,
  158. x3 = this._x1,
  159. y3 = this._y1,
  160. quads = [],
  161. node = this._root,
  162. q,
  163. i;
  164. if (node) quads.push(new Quad(node, x0, y0, x3, y3));
  165. if (radius == null) radius = Infinity;
  166. else {
  167. x0 = x - radius, y0 = y - radius;
  168. x3 = x + radius, y3 = y + radius;
  169. radius *= radius;
  170. }
  171. while (q = quads.pop()) {
  172. // Stop searching if this quadrant can’t contain a closer node.
  173. if (!(node = q.node)
  174. || (x1 = q.x0) > x3
  175. || (y1 = q.y0) > y3
  176. || (x2 = q.x1) < x0
  177. || (y2 = q.y1) < y0) continue;
  178. // Bisect the current quadrant.
  179. if (node.length) {
  180. var xm = (x1 + x2) / 2,
  181. ym = (y1 + y2) / 2;
  182. quads.push(
  183. new Quad(node[3], xm, ym, x2, y2),
  184. new Quad(node[2], x1, ym, xm, y2),
  185. new Quad(node[1], xm, y1, x2, ym),
  186. new Quad(node[0], x1, y1, xm, ym)
  187. );
  188. // Visit the closest quadrant first.
  189. if (i = (y >= ym) << 1 | (x >= xm)) {
  190. q = quads[quads.length - 1];
  191. quads[quads.length - 1] = quads[quads.length - 1 - i];
  192. quads[quads.length - 1 - i] = q;
  193. }
  194. }
  195. // Visit this point. (Visiting coincident points isn’t necessary!)
  196. else {
  197. var dx = x - +this._x.call(null, node.data),
  198. dy = y - +this._y.call(null, node.data),
  199. d2 = dx * dx + dy * dy;
  200. if (d2 < radius) {
  201. var d = Math.sqrt(radius = d2);
  202. x0 = x - d, y0 = y - d;
  203. x3 = x + d, y3 = y + d;
  204. data = node.data;
  205. }
  206. }
  207. }
  208. return data;
  209. }
  210. function tree_remove(d) {
  211. if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
  212. var parent,
  213. node = this._root,
  214. retainer,
  215. previous,
  216. next,
  217. x0 = this._x0,
  218. y0 = this._y0,
  219. x1 = this._x1,
  220. y1 = this._y1,
  221. x,
  222. y,
  223. xm,
  224. ym,
  225. right,
  226. bottom,
  227. i,
  228. j;
  229. // If the tree is empty, initialize the root as a leaf.
  230. if (!node) return this;
  231. // Find the leaf node for the point.
  232. // While descending, also retain the deepest parent with a non-removed sibling.
  233. if (node.length) while (true) {
  234. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  235. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  236. if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
  237. if (!node.length) break;
  238. if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
  239. }
  240. // Find the point to remove.
  241. while (node.data !== d) if (!(previous = node, node = node.next)) return this;
  242. if (next = node.next) delete node.next;
  243. // If there are multiple coincident points, remove just the point.
  244. if (previous) return (next ? previous.next = next : delete previous.next), this;
  245. // If this is the root point, remove it.
  246. if (!parent) return this._root = next, this;
  247. // Remove this leaf.
  248. next ? parent[i] = next : delete parent[i];
  249. // If the parent now contains exactly one leaf, collapse superfluous parents.
  250. if ((node = parent[0] || parent[1] || parent[2] || parent[3])
  251. && node === (parent[3] || parent[2] || parent[1] || parent[0])
  252. && !node.length) {
  253. if (retainer) retainer[j] = node;
  254. else this._root = node;
  255. }
  256. return this;
  257. }
  258. function removeAll(data) {
  259. for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
  260. return this;
  261. }
  262. function tree_root() {
  263. return this._root;
  264. }
  265. function tree_size() {
  266. var size = 0;
  267. this.visit(function(node) {
  268. if (!node.length) do ++size; while (node = node.next)
  269. });
  270. return size;
  271. }
  272. function tree_visit(callback) {
  273. var quads = [], q, node = this._root, child, x0, y0, x1, y1;
  274. if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
  275. while (q = quads.pop()) {
  276. if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
  277. var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
  278. if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
  279. if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
  280. if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
  281. if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
  282. }
  283. }
  284. return this;
  285. }
  286. function tree_visitAfter(callback) {
  287. var quads = [], next = [], q;
  288. if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
  289. while (q = quads.pop()) {
  290. var node = q.node;
  291. if (node.length) {
  292. var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
  293. if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
  294. if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
  295. if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
  296. if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
  297. }
  298. next.push(q);
  299. }
  300. while (q = next.pop()) {
  301. callback(q.node, q.x0, q.y0, q.x1, q.y1);
  302. }
  303. return this;
  304. }
  305. function defaultX(d) {
  306. return d[0];
  307. }
  308. function tree_x(_) {
  309. return arguments.length ? (this._x = _, this) : this._x;
  310. }
  311. function defaultY(d) {
  312. return d[1];
  313. }
  314. function tree_y(_) {
  315. return arguments.length ? (this._y = _, this) : this._y;
  316. }
  317. function quadtree(nodes, x, y) {
  318. var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
  319. return nodes == null ? tree : tree.addAll(nodes);
  320. }
  321. function Quadtree(x, y, x0, y0, x1, y1) {
  322. this._x = x;
  323. this._y = y;
  324. this._x0 = x0;
  325. this._y0 = y0;
  326. this._x1 = x1;
  327. this._y1 = y1;
  328. this._root = undefined;
  329. }
  330. function leaf_copy(leaf) {
  331. var copy = {data: leaf.data}, next = copy;
  332. while (leaf = leaf.next) next = next.next = {data: leaf.data};
  333. return copy;
  334. }
  335. var treeProto = quadtree.prototype = Quadtree.prototype;
  336. treeProto.copy = function() {
  337. var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
  338. node = this._root,
  339. nodes,
  340. child;
  341. if (!node) return copy;
  342. if (!node.length) return copy._root = leaf_copy(node), copy;
  343. nodes = [{source: node, target: copy._root = new Array(4)}];
  344. while (node = nodes.pop()) {
  345. for (var i = 0; i < 4; ++i) {
  346. if (child = node.source[i]) {
  347. if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
  348. else node.target[i] = leaf_copy(child);
  349. }
  350. }
  351. }
  352. return copy;
  353. };
  354. treeProto.add = tree_add;
  355. treeProto.addAll = addAll;
  356. treeProto.cover = tree_cover;
  357. treeProto.data = tree_data;
  358. treeProto.extent = tree_extent;
  359. treeProto.find = tree_find;
  360. treeProto.remove = tree_remove;
  361. treeProto.removeAll = removeAll;
  362. treeProto.root = tree_root;
  363. treeProto.size = tree_size;
  364. treeProto.visit = tree_visit;
  365. treeProto.visitAfter = tree_visitAfter;
  366. treeProto.x = tree_x;
  367. treeProto.y = tree_y;
  368. exports.quadtree = quadtree;
  369. Object.defineProperty(exports, '__esModule', { value: true });
  370. })));