blob: 18a3f61971d5695944b3829851aedd16bff5eb09 [file] [log] [blame]
rileya@google.com1f45e932012-09-05 16:10:59 +00001
2/*
3 * Copyright 2012 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include "SkRTree.h"
10#include "SkTSort.h"
11
12static inline uint32_t get_area(const SkIRect& rect);
13static inline uint32_t get_overlap(const SkIRect& rect1, const SkIRect& rect2);
14static inline uint32_t get_margin(const SkIRect& rect);
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000015static inline uint32_t get_overlap_increase(const SkIRect& rect1, const SkIRect& rect2,
rileya@google.com1f45e932012-09-05 16:10:59 +000016 SkIRect expandBy);
17static inline uint32_t get_area_increase(const SkIRect& rect1, SkIRect rect2);
18static inline void join_no_empty_check(const SkIRect& joinWith, SkIRect* out);
19
20///////////////////////////////////////////////////////////////////////////////////////////////////
21
22SkRTree* SkRTree::Create(int minChildren, int maxChildren) {
23 if (minChildren < maxChildren && (maxChildren + 1) / 2 >= minChildren &&
24 minChildren > 0 && maxChildren < static_cast<int>(SK_MaxU16)) {
25 return new SkRTree(minChildren, maxChildren);
26 }
27 return NULL;
28}
29
30SkRTree::SkRTree(int minChildren, int maxChildren)
31 : fMinChildren(minChildren)
32 , fMaxChildren(maxChildren)
33 , fNodeSize(sizeof(Node) + sizeof(Branch) * maxChildren)
34 , fCount(0)
35 , fNodes(fNodeSize * 256) {
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000036 SkASSERT(minChildren < maxChildren && minChildren > 0 && maxChildren <
rileya@google.com1f45e932012-09-05 16:10:59 +000037 static_cast<int>(SK_MaxU16));
38 SkASSERT((maxChildren + 1) / 2 >= minChildren);
39 this->validate();
40}
41
42SkRTree::~SkRTree() {
43 this->clear();
44}
45
46void SkRTree::insert(void* data, const SkIRect& bounds, bool defer) {
47 this->validate();
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000048 if (bounds.isEmpty()) {
rileya@google.com1f45e932012-09-05 16:10:59 +000049 SkASSERT(false);
50 return;
51 }
52 Branch newBranch;
53 newBranch.fBounds = bounds;
54 newBranch.fChild.data = data;
55 if (this->isEmpty()) {
56 // since a bulk-load into an existing tree is as of yet unimplemented (and arguably not
57 // of vital importance right now), we only batch up inserts if the tree is empty.
58 if (defer) {
59 fDeferredInserts.push(newBranch);
60 return;
61 } else {
62 fRoot.fChild.subtree = allocateNode(0);
63 fRoot.fChild.subtree->fNumChildren = 0;
64 }
65 }
66
67 Branch* newSibling = insert(fRoot.fChild.subtree, &newBranch);
68 fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree);
69
70 if (NULL != newSibling) {
71 Node* oldRoot = fRoot.fChild.subtree;
72 Node* newRoot = this->allocateNode(oldRoot->fLevel + 1);
73 newRoot->fNumChildren = 2;
74 *newRoot->child(0) = fRoot;
75 *newRoot->child(1) = *newSibling;
76 fRoot.fChild.subtree = newRoot;
77 fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree);
78 }
79
80 ++fCount;
81 this->validate();
82}
83
84void SkRTree::flushDeferredInserts() {
85 this->validate();
86 if (this->isEmpty() && fDeferredInserts.count() > 0) {
87 fCount = fDeferredInserts.count();
88 if (1 == fCount) {
89 fRoot.fChild.subtree = allocateNode(0);
90 fRoot.fChild.subtree->fNumChildren = 0;
91 this->insert(fRoot.fChild.subtree, &fDeferredInserts[0]);
92 fRoot.fBounds = fDeferredInserts[0].fBounds;
93 } else {
94 fRoot = this->bulkLoad(&fDeferredInserts);
95 }
96 } else {
97 // TODO: some algorithm for bulk loading into an already populated tree
98 SkASSERT(0 == fDeferredInserts.count());
99 }
100 fDeferredInserts.rewind();
101 this->validate();
102}
103
104void SkRTree::search(const SkIRect& query, SkTDArray<void*>* results) {
105 this->validate();
106 if (0 != fDeferredInserts.count()) {
107 this->flushDeferredInserts();
108 }
109 if (!this->isEmpty() && SkIRect::IntersectsNoEmptyCheck(fRoot.fBounds, query)) {
110 this->search(fRoot.fChild.subtree, query, results);
111 }
112 this->validate();
113}
114
115void SkRTree::clear() {
116 this->validate();
117 fNodes.reset();
118 fDeferredInserts.rewind();
119 fCount = 0;
120 this->validate();
121}
122
123SkRTree::Node* SkRTree::allocateNode(uint16_t level) {
124 Node* out = static_cast<Node*>(fNodes.allocThrow(fNodeSize));
125 out->fNumChildren = 0;
126 out->fLevel = level;
127 return out;
128}
129
130SkRTree::Branch* SkRTree::insert(Node* root, Branch* branch, uint16_t level) {
131 Branch* toInsert = branch;
132 if (root->fLevel != level) {
133 int childIndex = this->chooseSubtree(root, branch);
134 toInsert = this->insert(root->child(childIndex)->fChild.subtree, branch, level);
135 root->child(childIndex)->fBounds = this->computeBounds(
136 root->child(childIndex)->fChild.subtree);
137 }
138 if (NULL != toInsert) {
139 if (root->fNumChildren == fMaxChildren) {
140 // handle overflow by splitting. TODO: opportunistic reinsertion
141
142 // decide on a distribution to divide with
143 Node* newSibling = this->allocateNode(root->fLevel);
144 Branch* toDivide = SkNEW_ARRAY(Branch, fMaxChildren + 1);
145 for (int i = 0; i < fMaxChildren; ++i) {
146 toDivide[i] = *root->child(i);
147 }
148 toDivide[fMaxChildren] = *toInsert;
149 int splitIndex = this->distributeChildren(toDivide);
150
151 // divide up the branches
152 root->fNumChildren = splitIndex;
153 newSibling->fNumChildren = fMaxChildren + 1 - splitIndex;
154 for (int i = 0; i < splitIndex; ++i) {
155 *root->child(i) = toDivide[i];
156 }
157 for (int i = splitIndex; i < fMaxChildren + 1; ++i) {
158 *newSibling->child(i - splitIndex) = toDivide[i];
159 }
160 SkDELETE_ARRAY(toDivide);
161
162 // pass the new sibling branch up to the parent
163 branch->fChild.subtree = newSibling;
164 branch->fBounds = this->computeBounds(newSibling);
165 return branch;
166 } else {
167 *root->child(root->fNumChildren) = *toInsert;
168 ++root->fNumChildren;
169 return NULL;
170 }
171 }
172 return NULL;
173}
174
175int SkRTree::chooseSubtree(Node* root, Branch* branch) {
176 SkASSERT(!root->isLeaf());
177 if (1 < root->fLevel) {
178 // root's child pointers do not point to leaves, so minimize area increase
179 int32_t minAreaIncrease = SK_MaxS32;
180 int32_t minArea = SK_MaxS32;
181 int32_t bestSubtree = -1;
182 for (int i = 0; i < root->fNumChildren; ++i) {
183 const SkIRect& subtreeBounds = root->child(i)->fBounds;
184 int32_t areaIncrease = get_area_increase(subtreeBounds, branch->fBounds);
185 // break ties in favor of subtree with smallest area
186 if (areaIncrease < minAreaIncrease || (areaIncrease == minAreaIncrease &&
187 static_cast<int32_t>(get_area(subtreeBounds)) < minArea)) {
188 minAreaIncrease = areaIncrease;
189 minArea = get_area(subtreeBounds);
190 bestSubtree = i;
191 }
192 }
193 SkASSERT(-1 != bestSubtree);
194 return bestSubtree;
195 } else if (1 == root->fLevel) {
196 // root's child pointers do point to leaves, so minimize overlap increase
197 int32_t minOverlapIncrease = SK_MaxS32;
198 int32_t minAreaIncrease = SK_MaxS32;
199 int32_t bestSubtree = -1;
200 for (int32_t i = 0; i < root->fNumChildren; ++i) {
201 const SkIRect& subtreeBounds = root->child(i)->fBounds;
202 SkIRect expandedBounds = subtreeBounds;
203 join_no_empty_check(branch->fBounds, &expandedBounds);
204 int32_t overlap = 0;
205 for (int32_t j = 0; j < root->fNumChildren; ++j) {
206 if (j == i) continue;
207 // Note: this would be more correct if we subtracted the original pre-expanded
208 // overlap, but computing overlaps is expensive and omitting it doesn't seem to
209 // hurt query performance. See get_overlap_increase()
210 overlap += get_overlap(expandedBounds, root->child(j)->fBounds);
211 }
212 // break ties with lowest area increase
213 if (overlap < minOverlapIncrease || (overlap == minOverlapIncrease &&
skia.committer@gmail.com6c778162012-09-06 02:01:13 +0000214 static_cast<int32_t>(get_area_increase(branch->fBounds, subtreeBounds)) <
rileya@google.com1f45e932012-09-05 16:10:59 +0000215 minAreaIncrease)) {
216 minOverlapIncrease = overlap;
217 minAreaIncrease = get_area_increase(branch->fBounds, subtreeBounds);
218 bestSubtree = i;
219 }
220 }
221 return bestSubtree;
222 } else {
223 SkASSERT(false);
224 return 0;
225 }
226}
227
228SkIRect SkRTree::computeBounds(Node* n) {
229 SkIRect r = n->child(0)->fBounds;
230 for (int i = 1; i < n->fNumChildren; ++i) {
231 join_no_empty_check(n->child(i)->fBounds, &r);
232 }
233 return r;
234}
235
236int SkRTree::distributeChildren(Branch* children) {
237 // We have two sides to sort by on each of two axes:
238 const static SortSide sorts[2][2] = {
239 {&SkIRect::fLeft, &SkIRect::fRight},
240 {&SkIRect::fTop, &SkIRect::fBottom}
241 };
242
243 // We want to choose an axis to split on, then a distribution along that axis; we'll need
244 // three pieces of info: the split axis, the side to sort by on that axis, and the index
245 // to split the sorted array on.
246 int32_t sortSide = -1;
247 int32_t k = -1;
248 int32_t axis = -1;
249 int32_t bestS = SK_MaxS32;
250
251 // Evaluate each axis, we want the min summed margin-value (s) over all distributions
252 for (int i = 0; i < 2; ++i) {
253 int32_t minOverlap = SK_MaxS32;
254 int32_t minArea = SK_MaxS32;
255 int32_t axisBestK = 0;
256 int32_t axisBestSide = 0;
257 int32_t s = 0;
258
259 // Evaluate each sort
260 for (int j = 0; j < 2; ++j) {
261
262 SkQSort(sorts[i][j], children, children + fMaxChildren, &RectLessThan);
263
264 // Evaluate each split index
265 for (int32_t k = 1; k <= fMaxChildren - 2 * fMinChildren + 2; ++k) {
266 SkIRect r1 = children[0].fBounds;
267 SkIRect r2 = children[fMinChildren + k - 1].fBounds;
268 for (int32_t l = 1; l < fMinChildren - 1 + k; ++l) {
269 join_no_empty_check(children[l].fBounds, &r1);
skia.committer@gmail.com6c778162012-09-06 02:01:13 +0000270 }
rileya@google.com1f45e932012-09-05 16:10:59 +0000271 for (int32_t l = fMinChildren + k; l < fMaxChildren + 1; ++l) {
272 join_no_empty_check(children[l].fBounds, &r2);
273 }
274
275 int32_t area = get_area(r1) + get_area(r2);
276 int32_t overlap = get_overlap(r1, r2);
277 s += get_margin(r1) + get_margin(r2);
278
279 if (overlap < minOverlap || (overlap == minOverlap && area < minArea)) {
280 minOverlap = overlap;
281 minArea = area;
282 axisBestSide = j;
283 axisBestK = k;
284 }
285 }
286 }
287
288 if (s < bestS) {
289 bestS = s;
290 axis = i;
291 sortSide = axisBestSide;
292 k = axisBestK;
293 }
294 }
295
296 // replicate the sort of the winning distribution, (we can skip this if the last
297 // sort ended up being best)
298 if (!(axis == 1 && sortSide == 1)) {
299 SkQSort(sorts[axis][sortSide], children, children + fMaxChildren, &RectLessThan);
300 }
skia.committer@gmail.com6c778162012-09-06 02:01:13 +0000301
rileya@google.com1f45e932012-09-05 16:10:59 +0000302 return fMinChildren - 1 + k;
303}
304
305void SkRTree::search(Node* root, const SkIRect query, SkTDArray<void*>* results) const {
306 for (int i = 0; i < root->fNumChildren; ++i) {
307 if (SkIRect::IntersectsNoEmptyCheck(root->child(i)->fBounds, query)) {
308 if (root->isLeaf()) {
309 results->push(root->child(i)->fChild.data);
310 } else {
311 this->search(root->child(i)->fChild.subtree, query, results);
312 }
313 }
314 }
315}
316
317SkRTree::Branch SkRTree::bulkLoad(SkTDArray<Branch>* branches, int level) {
318 if (branches->count() == 1) {
319 // Only one branch: it will be the root
320 Branch out = (*branches)[0];
321 branches->rewind();
322 return out;
323 } else {
324 // First we sort the whole list by y coordinates
325 SkQSort<int, Branch>(level, branches->begin(), branches->end() - 1, &RectLessY);
skia.committer@gmail.com6c778162012-09-06 02:01:13 +0000326
rileya@google.com1f45e932012-09-05 16:10:59 +0000327 int numBranches = branches->count() / fMaxChildren;
328 int remainder = branches->count() % fMaxChildren;
329 int newBranches = 0;
330
331 if (0 != remainder) {
332 ++numBranches;
333 // If the remainder isn't enough to fill a node, we'll need to add fewer nodes to
334 // some other branches to make up for it
335 if (remainder >= fMinChildren) {
336 remainder = 0;
337 } else {
338 remainder = fMinChildren - remainder;
339 }
340 }
341
342 int numStrips = SkScalarCeil(SkScalarSqrt(SkIntToScalar(numBranches)));
343 int currentBranch = 0;
344
345 for (int i = 0; i < numStrips; ++i) {
346 int begin = currentBranch;
skia.committer@gmail.com6c778162012-09-06 02:01:13 +0000347 int end = currentBranch + numStrips * fMaxChildren - SkMin32(remainder,
rileya@google.com1f45e932012-09-05 16:10:59 +0000348 (fMaxChildren - fMinChildren) * numStrips);
349 if (end > branches->count()) {
350 end = branches->count();
351 }
352
353 // Now we sort horizontal strips of rectangles by their x coords
skia.committer@gmail.com6c778162012-09-06 02:01:13 +0000354 SkQSort<int, Branch>(level, branches->begin() + begin, branches->begin() + end - 1,
rileya@google.com1f45e932012-09-05 16:10:59 +0000355 &RectLessX);
356
357 for (int j = 0; j < numStrips && currentBranch < branches->count(); ++j) {
358 int incrementBy = fMaxChildren;
359 if (remainder != 0) {
360 // if need be, omit some nodes to make up for remainder
361 if (remainder <= fMaxChildren - fMinChildren) {
362 incrementBy -= remainder;
363 remainder = 0;
364 } else {
365 incrementBy = fMinChildren;
366 remainder -= fMaxChildren - fMinChildren;
367 }
368 }
369 Node* n = allocateNode(level);
370 n->fNumChildren = 1;
371 *n->child(0) = (*branches)[currentBranch];
372 Branch b;
373 b.fBounds = (*branches)[currentBranch].fBounds;
374 b.fChild.subtree = n;
375 ++currentBranch;
376 for (int k = 1; k < incrementBy && currentBranch < branches->count(); ++k) {
377 b.fBounds.join((*branches)[currentBranch].fBounds);
378 *n->child(k) = (*branches)[currentBranch];
379 ++n->fNumChildren;
380 ++currentBranch;
381 }
382 (*branches)[newBranches] = b;
383 ++newBranches;
384 }
385 }
386 branches->setCount(newBranches);
387 return this->bulkLoad(branches, level + 1);
388 }
389}
390
391void SkRTree::validate() {
392#ifdef SK_DEBUG
393 if (this->isEmpty()) {
394 return;
395 }
396 SkASSERT(fCount == this->validateSubtree(fRoot.fChild.subtree, fRoot.fBounds, true));
397#endif
398}
399
400int SkRTree::validateSubtree(Node* root, SkIRect bounds, bool isRoot) {
401 // make sure the pointer is pointing to a valid place
402 SkASSERT(fNodes.contains(static_cast<void*>(root)));
403
404 if (isRoot) {
405 // If the root of this subtree is the overall root, we have looser standards:
406 if (root->isLeaf()) {
407 SkASSERT(root->fNumChildren >= 1 && root->fNumChildren <= fMaxChildren);
408 } else {
409 SkASSERT(root->fNumChildren >= 2 && root->fNumChildren <= fMaxChildren);
410 }
411 } else {
412 SkASSERT(root->fNumChildren >= fMinChildren && root->fNumChildren <= fMaxChildren);
413 }
414
415 for (int i = 0; i < root->fNumChildren; ++i) {
416 SkASSERT(bounds.contains(root->child(i)->fBounds));
417 }
418
419 if (root->isLeaf()) {
420 SkASSERT(0 == root->fLevel);
421 return root->fNumChildren;
422 } else {
423 int childCount = 0;
424 for (int i = 0; i < root->fNumChildren; ++i) {
425 SkASSERT(root->child(i)->fChild.subtree->fLevel == root->fLevel - 1);
426 childCount += this->validateSubtree(root->child(i)->fChild.subtree,
427 root->child(i)->fBounds);
428 }
429 return childCount;
430 }
431}
432
433///////////////////////////////////////////////////////////////////////////////////////////////////
434
435static inline uint32_t get_area(const SkIRect& rect) {
436 return rect.width() * rect.height();
437}
438
439static inline uint32_t get_overlap(const SkIRect& rect1, const SkIRect& rect2) {
440 // I suspect there's a more efficient way of computing this...
441 return SkMax32(0, SkMin32(rect1.fRight, rect2.fRight) - SkMax32(rect1.fLeft, rect2.fLeft)) *
442 SkMax32(0, SkMin32(rect1.fBottom, rect2.fBottom) - SkMax32(rect1.fTop, rect2.fTop));
443}
444
445// Get the margin (aka perimeter)
446static inline uint32_t get_margin(const SkIRect& rect) {
447 return 2 * (rect.width() + rect.height());
448}
449
skia.committer@gmail.com6c778162012-09-06 02:01:13 +0000450static inline uint32_t get_overlap_increase(const SkIRect& rect1, const SkIRect& rect2,
rileya@google.com1f45e932012-09-05 16:10:59 +0000451 SkIRect expandBy) {
452 join_no_empty_check(rect1, &expandBy);
453 return get_overlap(expandBy, rect2) - get_overlap(rect1, rect2);
454}
455
456static inline uint32_t get_area_increase(const SkIRect& rect1, SkIRect rect2) {
457 join_no_empty_check(rect1, &rect2);
458 return get_area(rect2) - get_area(rect1);
459}
460
461// Expand 'out' to include 'joinWith'
462static inline void join_no_empty_check(const SkIRect& joinWith, SkIRect* out) {
463 // since we check for empty bounds on insert, we know we'll never have empty rects
464 // and we can save the empty check that SkIRect::join requires
465 if (joinWith.fLeft < out->fLeft) { out->fLeft = joinWith.fLeft; }
466 if (joinWith.fTop < out->fTop) { out->fTop = joinWith.fTop; }
467 if (joinWith.fRight > out->fRight) { out->fRight = joinWith.fRight; }
468 if (joinWith.fBottom > out->fBottom) { out->fBottom = joinWith.fBottom; }
469}
470