1 | 'use strict';
|
2 | var utils = require('./utils');
|
3 | var Promise = require('bluebird');
|
4 | var uuid = require('node-uuid');
|
5 | module.exports = function (self, array) {
|
6 | var todo = [load(self, array)];
|
7 | var current;
|
8 | var done = [];
|
9 | var i, j, clen, len, node;
|
10 | function strip(item) {
|
11 | var out = {
|
12 | id: item.id,
|
13 | bbox: [item.bbox[0].slice(), item.bbox[1].slice()]
|
14 | };
|
15 | if ('leaf' in item) {
|
16 | out.leaf = item.leaf;
|
17 | }
|
18 | return out;
|
19 | }
|
20 | while (todo.length) {
|
21 | current = todo;
|
22 | todo = [];
|
23 | i = -1;
|
24 | len = current.length;
|
25 | while (++i < len) {
|
26 | node = current[i];
|
27 | clen = node.children.length;
|
28 | j = -1;
|
29 |
|
30 | done.push(node);
|
31 | while (++j < clen) {
|
32 | if (node.children[j].children) {
|
33 | todo.push(node.children[j]);
|
34 | } else {
|
35 | node.children[j].leaf = true;
|
36 | done.push(node.children[j]);
|
37 | }
|
38 | node.children[j] = strip(node.children[j]);
|
39 | }
|
40 | }
|
41 | }
|
42 | return done;
|
43 | };
|
44 | function load(self, array, level, height) {
|
45 | level = level || 0;
|
46 | var len = array.length;
|
47 | var node;
|
48 |
|
49 | if (len <= self.MAX) {
|
50 | node = {
|
51 | children: array,
|
52 | level: 1,
|
53 | id: uuid.v4()
|
54 | };
|
55 | node.bbox = node.children.length > 1? node.children.reduce(utils.enlarger): node.children[0].bbox;
|
56 | return node;
|
57 | }
|
58 |
|
59 | if (!level) {
|
60 |
|
61 | height = Math.ceil(Math.log(len) / Math.log(self.MAX));
|
62 |
|
63 |
|
64 |
|
65 |
|
66 | utils.chooseAxis(array, self.MIN);
|
67 | }
|
68 |
|
69 |
|
70 |
|
71 | node = {
|
72 | children: [],
|
73 | id: uuid.v4()
|
74 | };
|
75 |
|
76 | var len1 = Math.ceil(len / self.MAX) * Math.ceil(Math.sqrt(self.MAX));
|
77 | var len2 = utils.max(Math.ceil(len / self.MAX), self.MIN);
|
78 | var i = 0 - len1;
|
79 | var j, slice, sliceLen, childNode;
|
80 | var out = [];
|
81 |
|
82 |
|
83 | while ((i += len1) < len) {
|
84 | if ((i + len1 + len1) > len) {
|
85 | slice = array.slice(i);
|
86 | i += len1;
|
87 | } else {
|
88 | slice = array.slice(i, i + len1);
|
89 | }
|
90 | utils.chooseAxis(slice, self.MIN);
|
91 | j = 0 - len2;
|
92 | sliceLen = slice.length;
|
93 | while ((j += len2) < sliceLen) {
|
94 |
|
95 | out.push(slice.slice(j, j + len2));
|
96 | }
|
97 | }
|
98 | var children = out.map(function (slice) {
|
99 | return load(self, slice, level + 1, height - 1);
|
100 | });
|
101 | node.children = children;
|
102 | node.bbox = node.children.length > 1? node.children.reduce(utils.enlarger): node.children[0].bbox;
|
103 | node.level = (Math.max.apply(Math, node.children.map(function (child) {
|
104 | return child.level;
|
105 | })) + 1);
|
106 | return node;
|
107 | } |
\ | No newline at end of file |