UNPKG

3.29 kBJavaScriptView Raw
1'use strict';
2var utils = require('./utils');
3var uuid = require('node-uuid');
4var checkNew = require('./checkNew');
5module.exports = insert;
6
7function insert(self, id, bbox, nodeID, height, store) {
8 store = store || self.store;
9 if (!nodeID) {
10 if (!self.root) {
11 return store.batch([
12 {
13 key:'root',
14 value: {
15 bbox: bbox,
16 id: 'root',
17 level: 1,
18 children: [{
19 id: id,
20 bbox: bbox,
21 leaf:true
22 }]
23 }
24 },
25 {
26 key:'$' + id,
27 value:[bbox]
28 }
29 ]).then(function (resp){
30 self.root = 'root';
31 return resp;
32 });
33 } else {
34 return insert(self, id, bbox, self.root, height, store);
35 }
36 }
37 return choosePath(store, bbox, nodeID, [], height).then(function (path) {
38 var leaf = path[path.length - 1];
39 if (height) {
40 leaf.children.push({
41 id: id,
42 bbox: bbox
43 });
44 } else {
45 leaf.children.push({
46 id: id,
47 bbox: bbox,
48 leaf: true
49 });
50 }
51 leaf.bbox = utils.enlarge(bbox, leaf.bbox);
52 if (leaf.children.length >= self.MAX) {
53 splitLeaf(self, path);
54 }
55 return updatePath(store, path);
56 });
57}
58
59// much of this from rbush
60function splitLeaf(self, path) {
61 var i = path.length;
62 var newNode, splitedNode;
63 while (--i && path[i].children.length >= self.MAX) {
64 newNode = utils.splitNode(path[i], self.MIN);
65 path[i - 1].children.push({
66 id: newNode.id,
67 bbox: newNode.bbox
68 });
69 path.push(newNode);
70 }
71 if (i === 0 && path[0].children.length >= self.MAX) {
72 newNode = {
73 id: uuid.v4(),
74 bbox: [path[0].bbox[0].slice(), path[0].bbox[1].slice()],
75 children: path[0].children,
76 level: path[0].level
77 };
78 path.push(newNode);
79 splitedNode = utils.splitNode(newNode, self.MIN);
80 path.push(splitedNode);
81 path[0].level++;
82 path[0].children = [{
83 id: newNode.id,
84 bbox: newNode.bbox
85 }, {
86 id: splitedNode.id,
87 bbox: splitedNode.bbox
88 }];
89 }
90}
91
92
93function updatePath (store, path) {
94 return store.batch(path.map(function (item) {
95 return {
96 type: 'put',
97 key: item.id,
98 value: item
99 };
100 }));
101}
102function choosePath(store, bbox, rootID, path, height) {
103 path = path || [];
104 return store.get(rootID).then(function (node) {
105 path.push(node);
106 if (node.children[0].leaf || node.height < height) {
107 return path;
108 }
109 var bestFit = findBestFit(bbox, node.children);
110 node.children[bestFit.index].bbox = bestFit.bbox;
111 node.bbox = utils.enlarge(bbox, node.bbox);
112 return choosePath(store, bbox, bestFit.id, path);
113 });
114}
115
116function findBestFit(bbox, children) {
117 var i = 0;
118 var bestFitNode = children[0];
119 var lastEnlargment = utils.enlarge(bbox, children[0].bbox);
120 var bestArea = utils.area(lastEnlargment);
121 var index = 0;
122 var len = children.length;
123 var area, enlarged;
124 while (++i < len) {
125 enlarged = utils.enlarge(bbox, children[i].bbox);
126 area = utils.area(enlarged);
127 if (area < bestArea) {
128 index = i;
129 bestFitNode = children[i];
130 bestArea = area;
131 }
132 }
133 return {
134 id: bestFitNode.id,
135 bbox: lastEnlargment,
136 index: index
137 };
138}
\No newline at end of file