1 | 'use strict';
|
2 | var uuid = require('node-uuid');
|
3 | exports.contains = contains;
|
4 | function contains(a, b) {
|
5 | var i = -1;
|
6 | var len = a[0].length;
|
7 | while (++i < len) {
|
8 | if (a[0][i] > b[0][i] || a[1][i] < b[1][i]) {
|
9 | return false;
|
10 | }
|
11 | }
|
12 | return true;
|
13 | }
|
14 | exports.intersects = intersects;
|
15 | function intersects(a, b) {
|
16 | var i = -1;
|
17 | var len = b[0].length;
|
18 | while (++i < len) {
|
19 | if (b[0][i] > a[1][i] || a[0][i] > b[1][i]) {
|
20 | return false;
|
21 | }
|
22 | }
|
23 | return true;
|
24 | }
|
25 |
|
26 | exports.min = min;
|
27 | function min(a, b) {
|
28 | if (a < b) {
|
29 | return a;
|
30 | } else {
|
31 | return b;
|
32 | }
|
33 | }
|
34 | exports.max = max;
|
35 | function max(a, b) {
|
36 | if (a > b) {
|
37 | return a;
|
38 | } else {
|
39 | return b;
|
40 | }
|
41 | }
|
42 | exports.enlarge = enlarge;
|
43 | function enlarge(a, b) {
|
44 | var len = min(a[0].length, b[0].length);
|
45 | var out = [
|
46 | new Array(len),
|
47 | new Array(len)
|
48 | ];
|
49 | var i = -1;
|
50 | while (++i < len) {
|
51 | out[0][i] = min(a[0][i], b[0][i]);
|
52 | out[1][i] = max(a[1][i], b[1][i]);
|
53 | }
|
54 | return out;
|
55 | }
|
56 | exports.intersection = intersection;
|
57 | function intersection(a, b) {
|
58 | var len = min(a[0].length, b[0].length);
|
59 | var out = [
|
60 | new Array(len),
|
61 | new Array(len)
|
62 | ];
|
63 | var i = -1;
|
64 | while (++i < len) {
|
65 | out[0][i] = max(a[0][i], b[0][i]);
|
66 | out[1][i] = min(a[1][i], b[1][i]);
|
67 | }
|
68 | return out;
|
69 | }
|
70 | exports.area = area;
|
71 | function area(box) {
|
72 | var len = box[0].length;
|
73 | var out = 1;
|
74 | var i = -1;
|
75 | while (++i < len) {
|
76 | out *= (box[1][i] - box[0][i]);
|
77 | }
|
78 | return out;
|
79 | }
|
80 | exports.margin = margin;
|
81 | function margin(box) {
|
82 | var len = box[0].length;
|
83 | var out = 0;
|
84 | var i = -1;
|
85 | while (++i < len) {
|
86 | out += (box[1][i] - box[0][i]);
|
87 | }
|
88 | return out;
|
89 | }
|
90 |
|
91 | exports.enlarger = enlarger;
|
92 | function enlarger (a, b) {
|
93 | if (a.bbox) {
|
94 | a = a.bbox;
|
95 | }
|
96 | return enlarge(a, b.bbox);
|
97 | }
|
98 | exports.equals = equals;
|
99 | function equals (a, b) {
|
100 | var len = a[0].length;
|
101 | var i = -1;
|
102 | while (++i < len) {
|
103 | if(a[0][i] !== b[0][i] || a[1][i] !== b[1][i]) {
|
104 | return false;
|
105 | }
|
106 | }
|
107 | return true;
|
108 | }
|
109 | exports.chooseAxis = chooseAxis;
|
110 | function chooseAxis(children, MIN) {
|
111 | var indices = children[0].bbox[0].length;
|
112 | var i = 0;
|
113 | var minMargin = allDistMargin(children, 0, MIN);
|
114 | var mindex = 0;
|
115 | var margin;
|
116 | while (++i < indices) {
|
117 | margin = allDistMargin(children, i, MIN);
|
118 | if (margin < minMargin) {
|
119 | mindex = i;
|
120 | minMargin = margin;
|
121 | }
|
122 | }
|
123 | if (mindex !== (i - 1)) {
|
124 | children.sort(function (a, b) {
|
125 | return a.bbox[0][mindex] - b.bbox[0][mindex];
|
126 | });
|
127 | }
|
128 | }
|
129 | exports.allDistMargin = allDistMargin;
|
130 | function allDistMargin(children, index, MIN) {
|
131 | var len = children.length;
|
132 |
|
133 | children.sort(function (a, b) {
|
134 | return a.bbox[0][index] - b.bbox[0][index];
|
135 | });
|
136 |
|
137 | var leftBBox = children.slice(0, MIN).reduce(enlarger);
|
138 | var rightBBox = children.slice(len - MIN, len).reduce(enlarger);
|
139 | var calcedMargin = margin(leftBBox) + margin(rightBBox);
|
140 | var i = MIN - 1;
|
141 | var child;
|
142 | while (++i < len - MIN) {
|
143 | child = children[i];
|
144 | leftBBox = enlarge(leftBBox, child.bbox);
|
145 | calcedMargin += margin(leftBBox);
|
146 | }
|
147 | i = len - MIN;
|
148 | while (--i >= MIN) {
|
149 | child = children[i];
|
150 | rightBBox = enlarge(rightBBox, child.bbox);
|
151 | calcedMargin += margin(rightBBox);
|
152 | }
|
153 |
|
154 | return calcedMargin;
|
155 | }
|
156 | exports.chooseIndex = chooseIndex;
|
157 | function chooseIndex(children, MIN) {
|
158 | var len = children.length;
|
159 |
|
160 | var i = MIN;
|
161 | var leftBBox = children.slice(0, i).reduce(enlarger);
|
162 | var rightBBox = children.slice(len - i, len).reduce(enlarger);
|
163 | var area, overlap;
|
164 | var minOverlap = exports.area(intersection(leftBBox, rightBBox));
|
165 | var minArea = exports.area(leftBBox) + exports.area(rightBBox);
|
166 | var mindex = i;
|
167 | while (++i < len) {
|
168 | leftBBox = children.slice(0, i).reduce(enlarger);
|
169 | rightBBox = children.slice(len - i, len).reduce(enlarger);
|
170 | overlap = exports.area(intersection(leftBBox, rightBBox));
|
171 | area = exports.area(leftBBox) + exports.area(rightBBox);
|
172 | if (overlap < minOverlap || (overlap === minOverlap && area < minArea)) {
|
173 | minOverlap = overlap;
|
174 | mindex = i;
|
175 |
|
176 | minArea = area < minArea ? area : minArea;
|
177 | }
|
178 | }
|
179 | return mindex;
|
180 | }
|
181 | exports.splitNode = splitNode;
|
182 | function splitNode(node, MIN) {
|
183 | chooseAxis(node.children, MIN);
|
184 | var index = chooseIndex(node.children, MIN);
|
185 | var newNode = {
|
186 | id: uuid.v4(),
|
187 | level: node.level
|
188 | };
|
189 | newNode.children = node.children.slice(0, index);
|
190 | node.children = node.children.slice(index, node.children.length);
|
191 | newNode.bbox = newNode.children.reduce(enlarger);
|
192 | node.bbox = node.children.reduce(enlarger);
|
193 | return newNode;
|
194 | } |
\ | No newline at end of file |