1 | 'use strict';
|
2 | var Promise = require('bluebird');
|
3 | var utils = require('./utils');
|
4 | module.exports = remove;
|
5 | function remove(self, id, bbox, nodeID, store) {
|
6 | store = store || self.store;
|
7 | if (!nodeID) {
|
8 | if (!self.root) {
|
9 | return Promise.reject(new Error('can\'t delete it if there is nothing in the tree'));
|
10 | } else {
|
11 | if (!bbox) {
|
12 | return store.get('$' + id).then(function (bboxen) {
|
13 | return Promise.all(bboxen.map(function (bbox) {
|
14 | return remove(self, id, bbox, self.root, store);
|
15 | }));
|
16 | }, function () {
|
17 | throw new Error ('not found');
|
18 | });
|
19 | } else {
|
20 | return remove(self, id, bbox, self.root, store);
|
21 | }
|
22 | }
|
23 | }
|
24 | return store.get(nodeID).then(function (root) {
|
25 | return findPath(store, id, bbox, [[root]]);
|
26 | }).then(function (path) {
|
27 | var node = path.pop();
|
28 | var toRemove = [];
|
29 | var toUpdate = [];
|
30 | var i = path.length - 1;
|
31 | var tail = path[i];
|
32 | tail.children.splice(indexById(id, tail.children), 1);
|
33 | var bbox, index;
|
34 | while (i) {
|
35 | i--;
|
36 | node = tail;
|
37 | tail = path[i];
|
38 | if (!node.children.length) {
|
39 | tail.children.splice(indexById(node.id, tail.children), 1);
|
40 | toRemove.push(node.id);
|
41 | toUpdate.push(tail);
|
42 | continue;
|
43 | }
|
44 | bbox = node.bbox;
|
45 | node.bbox = node.children.reduce(utils.enlarger);
|
46 | if (utils.equals(bbox, node.bbox)) {
|
47 | break;
|
48 | }
|
49 | if (toUpdate.indexOf(node) === -1) {
|
50 | toUpdate.push(node);
|
51 | }
|
52 | index = indexById(node.id, tail.children);
|
53 | tail.children[index].bbox = [node.bbox[0].slice(), node.bbox[1].slice()];
|
54 | if (toUpdate.indexOf(tail) === -1) {
|
55 | toUpdate.push(tail);
|
56 | }
|
57 | }
|
58 | return store.batch(toRemove.map(function (key) {
|
59 | return {
|
60 | key: key,
|
61 | type: 'del'
|
62 | };
|
63 | }).concat(toUpdate.map(function (item) {
|
64 | return {
|
65 | key: item.id,
|
66 | value: item
|
67 | };
|
68 | }), [{type: 'del', key: '$' + id}]));
|
69 | });
|
70 | }
|
71 |
|
72 | function indexById(id, children) {
|
73 | var i = -1;
|
74 | var len = children.length;
|
75 | while (++i < len) {
|
76 | if (id === children[i].id) {
|
77 | return i;
|
78 | }
|
79 | }
|
80 | throw new Error('id not in node it is claimed to be in');
|
81 | }
|
82 | function findPath(store, id, bbox, queue) {
|
83 | if (!queue.length) {
|
84 | throw new Error('not found');
|
85 | }
|
86 | var path = queue.pop();
|
87 | var node = path[path.length - 1];
|
88 | var candidates = [];
|
89 | var i = -1;
|
90 | var len = node.children.length;
|
91 | var child;
|
92 | while (++i < len) {
|
93 | child = node.children[i];
|
94 | if (child.id === id && utils.equals(child.bbox, bbox)) {
|
95 | path.push(child);
|
96 | return path;
|
97 | } else if (!child.leaf){
|
98 | if (utils.contains(child.bbox, bbox)) {
|
99 | candidates.push(child.id);
|
100 | }
|
101 | }
|
102 | }
|
103 | return Promise.all(candidates.map(function (id) {
|
104 | return store.get(id);
|
105 | })).then(function (items) {
|
106 | items.forEach(function (item) {
|
107 | var nPath = path.slice();
|
108 | nPath.push(item);
|
109 | queue.push(nPath);
|
110 | });
|
111 | return findPath(store, id, bbox, queue);
|
112 | });
|
113 | } |
\ | No newline at end of file |