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