Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: src/core/SkRTree.h

Issue 734723002: Prune SkRTree (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: nits Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkBBHFactory.cpp ('k') | src/core/SkRTree.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2012 Google Inc. 3 * Copyright 2012 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #ifndef SkRTree_DEFINED 9 #ifndef SkRTree_DEFINED
10 #define SkRTree_DEFINED 10 #define SkRTree_DEFINED
11 11
12 #include "SkBBoxHierarchy.h"
12 #include "SkRect.h" 13 #include "SkRect.h"
13 #include "SkTDArray.h" 14 #include "SkTDArray.h"
14 #include "SkChunkAlloc.h"
15 #include "SkBBoxHierarchy.h"
16 15
17 /** 16 /**
18 * An R-Tree implementation. In short, it is a balanced n-ary tree containing a hierarchy of 17 * An R-Tree implementation. In short, it is a balanced n-ary tree containing a hierarchy of
19 * bounding rectangles. 18 * bounding rectangles.
20 * 19 *
21 * Much like a B-Tree it maintains balance by enforcing minimum and maximum chil d counts, and 20 * It only supports bulk-loading, i.e. creation from a batch of bounding rectang les.
22 * splitting nodes when they become overfull. Unlike B-trees, however, we're usi ng spatial data; so 21 * This performs a bottom-up bulk load using the STR (sort-tile-recursive) algor ithm.
23 * there isn't a canonical ordering to use when choosing insertion locations and splitting
24 * distributions. A variety of heuristics have been proposed for these problems; here, we're using
25 * something resembling an R*-tree, which attempts to minimize area and overlap during insertion,
26 * and aims to minimize a combination of margin, overlap, and area when splittin g.
27 * 22 *
28 * One detail that is thus far unimplemented that may improve tree quality is at tempting to remove 23 * TODO: Experiment with other bulk-load algorithms (in particular the Hilbert p ack variant,
29 * and reinsert nodes when they become full, instead of immediately splitting (n odes that may have 24 * which groups rects by position on the Hilbert curve, is probably worth a look ). There also
30 * been placed well early on may hurt the tree later when more nodes have been a dded; removing 25 * exist top-down bulk load variants (VAMSplit, TopDownGreedy, etc).
31 * and reinserting nodes generally helps reduce overlap and make a better tree). Deletion of nodes
32 * is also unimplemented.
33 * 26 *
34 * For more details see: 27 * For more details see:
35 * 28 *
36 * Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). "The R*-tree : 29 * Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). "The R*-tree :
37 * an efficient and robust access method for points and rectangles" 30 * an efficient and robust access method for points and rectangles"
38 *
39 * It also supports bulk-loading from a batch of bounds and values; if you don't require the tree
40 * to be usable in its intermediate states while it is being constructed, this i s significantly
41 * quicker than individual insertions and produces more consistent trees.
42 */ 31 */
43 class SkRTree : public SkBBoxHierarchy { 32 class SkRTree : public SkBBoxHierarchy {
44 public: 33 public:
45 SK_DECLARE_INST_COUNT(SkRTree) 34 SK_DECLARE_INST_COUNT(SkRTree)
46 35
47 /** 36 /**
48 * Create a new R-Tree with specified min/max child counts.
49 * The child counts are valid iff:
50 * - (max + 1) / 2 >= min (splitting an overfull node must be enough to popu late 2 nodes)
51 * - min < max
52 * - min > 0
53 * - max < SK_MaxU16
54 * If you have some prior information about the distribution of bounds you'r e expecting, you 37 * If you have some prior information about the distribution of bounds you'r e expecting, you
55 * can provide an optional aspect ratio parameter. This allows the bulk-load algorithm to create 38 * can provide an optional aspect ratio parameter. This allows the bulk-load algorithm to
56 * better proportioned tiles of rectangles. 39 * create better proportioned tiles of rectangles.
57 */ 40 */
58 static SkRTree* Create(int minChildren, int maxChildren, SkScalar aspectRati o = 1, 41 explicit SkRTree(SkScalar aspectRatio = 1);
59 bool orderWhenBulkLoading = true); 42 virtual ~SkRTree() {}
60 virtual ~SkRTree();
61 43
62 virtual void insert(SkAutoTMalloc<SkRect>* boundsArray, int N) SK_OVERRIDE; 44 virtual void insert(SkAutoTMalloc<SkRect>* boundsArray, int N) SK_OVERRIDE;
63 virtual void search(const SkRect& query, SkTDArray<unsigned>* results) const SK_OVERRIDE; 45 virtual void search(const SkRect& query, SkTDArray<unsigned>* results) const SK_OVERRIDE;
64 46
65 void clear(); 47 // Methods and constants below here are only public for tests.
48
66 // Return the depth of the tree structure. 49 // Return the depth of the tree structure.
67 int getDepth() const { return this->isEmpty() ? 0 : fRoot.fChild.subtree->fL evel + 1; } 50 int getDepth() const { return fCount ? fRoot.fSubtree->fLevel + 1 : 0; }
68 // Insertion count (not overall node count, which may be greater). 51 // Insertion count (not overall node count, which may be greater).
69 int getCount() const { return fCount; } 52 int getCount() const { return fCount; }
70 53
54 // These values were empirically determined to produce reasonable performanc e in most cases.
55 static const int kMinChildren = 6,
56 kMaxChildren = 11;
71 private: 57 private:
72 bool isEmpty() const { return 0 == this->getCount(); }
73
74 struct Node; 58 struct Node;
75 59
76 /**
77 * A branch of the tree, this may contain a pointer to another interior node , or a data value
78 */
79 struct Branch { 60 struct Branch {
80 union { 61 union {
81 Node* subtree; 62 Node* fSubtree;
82 unsigned opIndex; 63 unsigned fOpIndex;
83 } fChild; 64 };
84 SkIRect fBounds; 65 SkRect fBounds;
85 }; 66 };
86 67
87 /**
88 * A node in the tree, has between fMinChildren and fMaxChildren (the root i s a special case)
89 */
90 struct Node { 68 struct Node {
91 uint16_t fNumChildren; 69 uint16_t fNumChildren;
robertphillips 2014/11/18 17:26:43 Can we do with out fLevel now ?
mtklein 2014/11/18 17:34:00 Yes, I think I can get rid of that. Didn't bother
92 uint16_t fLevel; 70 uint16_t fLevel;
93 bool isLeaf() { return 0 == fLevel; } 71 Branch fChildren[kMaxChildren];
94 // Since we want to be able to pick min/max child counts at runtime, we assume the creator
95 // has allocated sufficient space directly after us in memory, and index into that space
96 Branch* child(size_t index) {
97 return reinterpret_cast<Branch*>(this + 1) + index;
98 }
99 }; 72 };
100 73
101 typedef int32_t SkIRect::*SortSide; 74 void search(Node* root, const SkRect& query, SkTDArray<unsigned>* results) c onst;
102 75
103 // Helper for sorting our children arrays by sides of their rects 76 // Consumes the input array.
104 struct RectLessThan {
105 RectLessThan(SkRTree::SortSide side) : fSide(side) { }
106 bool operator()(const SkRTree::Branch lhs, const SkRTree::Branch rhs) co nst {
107 return lhs.fBounds.*fSide < rhs.fBounds.*fSide;
108 }
109 private:
110 const SkRTree::SortSide fSide;
111 };
112
113 struct RectLessX {
114 bool operator()(const SkRTree::Branch lhs, const SkRTree::Branch rhs) {
115 return ((lhs.fBounds.fRight - lhs.fBounds.fLeft) >> 1) <
116 ((rhs.fBounds.fRight - lhs.fBounds.fLeft) >> 1);
117 }
118 };
119
120 struct RectLessY {
121 bool operator()(const SkRTree::Branch lhs, const SkRTree::Branch rhs) {
122 return ((lhs.fBounds.fBottom - lhs.fBounds.fTop) >> 1) <
123 ((rhs.fBounds.fBottom - lhs.fBounds.fTop) >> 1);
124 }
125 };
126
127 SkRTree(int minChildren, int maxChildren, SkScalar aspectRatio, bool orderWh enBulkLoading);
128
129 /**
130 * Recursively descend the tree to find an insertion position for 'branch', updates
131 * bounding boxes on the way up.
132 */
133 Branch* insert(Node* root, Branch* branch, uint16_t level = 0);
134
135 int chooseSubtree(Node* root, Branch* branch);
136 SkIRect computeBounds(Node* n);
137 int distributeChildren(Branch* children);
138 void search(Node* root, const SkIRect query, SkTDArray<unsigned>* results) c onst;
139
140 /**
141 * This performs a bottom-up bulk load using the STR (sort-tile-recursive) a lgorithm, this
142 * seems to generally produce better, more consistent trees at significantly lower cost than
143 * repeated insertions.
144 *
145 * This consumes the input array.
146 *
147 * TODO: Experiment with other bulk-load algorithms (in particular the Hilbe rt pack variant,
148 * which groups rects by position on the Hilbert curve, is probably worth a look). There also
149 * exist top-down bulk load variants (VAMSplit, TopDownGreedy, etc).
150 */
151 Branch bulkLoad(SkTDArray<Branch>* branches, int level = 0); 77 Branch bulkLoad(SkTDArray<Branch>* branches, int level = 0);
152 78
153 void validate() const; 79 // How many times will bulkLoad() call allocateNodeAtLevel()?
154 int validateSubtree(Node* root, SkIRect bounds, bool isRoot = false) const; 80 static int CountNodes(int branches, SkScalar aspectRatio);
155 81
156 const int fMinChildren; 82 Node* allocateNodeAtLevel(uint16_t level);
157 const int fMaxChildren;
158 const size_t fNodeSize;
159 83
160 // This is the count of data elements (rather than total nodes in the tree) 84 // This is the count of data elements (rather than total nodes in the tree)
161 int fCount; 85 int fCount;
162 86 SkScalar fAspectRatio;
163 Branch fRoot; 87 Branch fRoot;
164 SkChunkAlloc fNodes; 88 SkTDArray<Node> fNodes;
165 SkScalar fAspectRatio;
166 bool fSortWhenBulkLoading;
167
168 Node* allocateNode(uint16_t level);
169 89
170 typedef SkBBoxHierarchy INHERITED; 90 typedef SkBBoxHierarchy INHERITED;
171 }; 91 };
172 92
173 #endif 93 #endif
OLDNEW
« no previous file with comments | « src/core/SkBBHFactory.cpp ('k') | src/core/SkRTree.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698