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

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

Issue 187233002: Fast implementation of QuadTree (Closed) Base URL: https://skia.googlesource.com/skia.git@bbh_select
Patch Set: Delete dead code Created 6 years, 9 months 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 | « no previous file | src/core/SkQuadTree.cpp » ('j') | src/core/SkQuadTree.cpp » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkQuadTree_DEFINED 8 #ifndef SkQuadTree_DEFINED
9 #define SkQuadTree_DEFINED 9 #define SkQuadTree_DEFINED
10 10
11 #include "SkRect.h" 11 #include "SkRect.h"
12 #include "SkTDArray.h" 12 #include "SkTDArray.h"
13 #include "SkBBoxHierarchy.h" 13 #include "SkBBoxHierarchy.h"
14 #include "SkChunkAlloc.h"
15
16 /**
17 * An implementation of an intrusive singly linked list.
18 * The type T must have a field fNext that is visible to the list.
19 * The list does not maintain ownership of any of it's elements, or ever delete
tomhudson 2014/03/05 11:56:56 Nit: no apostrophe
iancottrell 2014/03/05 12:11:16 Done.
20 * them.
21 * The fNext must be null on any object handed to push, and will be NULL when
22 * returned from pop. It is free to use while the object is not in the a list.
23 */
24 template<typename T> class SkSList {
25 public:
26 SkSList() : fHead(NULL), fCount(0) {}
27
28 /**
29 * Push an item onto the head of the list.
30 * This method is *not* thread safe.
31 */
32 void push(T* entry) {
33 SkASSERT(entry->fNext == NULL);
34 entry->fNext = fHead;
35 fHead = entry;
36 ++fCount;
37 }
38
39 /**
40 * Takes all the items from another list.
41 */
42 void takeAll(SkSList<T>& other) {
43 if (isEmpty()) {
44 swap(other);
45 return;
46 }
47 while(!other.isEmpty()) {
tomhudson 2014/03/05 11:56:56 Can't we just graft the other list onto this one?
iancottrell 2014/03/05 12:11:16 Yes, I decided it made the code less readable for
48 push(other.pop());
49 }
50 }
51
52 /**
53 * Pop an item from the head of the list.
54 * Returns NULL if the list is empty.
55 * This method is *not* thread safe.
56 */
57 T* pop() {
58 if (fHead == NULL) {
59 return NULL;
60 }
61 T* result = fHead;
62 fHead = result->fNext;
63 result->fNext = NULL;
64 --fCount;
65 return result;
66 }
67
68 T* head() {
69 return fHead;
70 }
71
72 /**
73 * Returns true if the list has no elements.
74 */
75 bool isEmpty() {
76 return fHead == NULL;
77 }
78
79 /**
80 * Swaps the contents of this list with another one.
81 */
82 void swap(SkSList<T>& other) {
83 SkTSwap(fHead, other.fHead);
84 }
85
86 /**
87 * Returns the count of elements in the list.
88 */
89 int getCount() {
90 return fCount;
91 }
92 private:
93 T* fHead;
94 int fCount;
95 };
96
97
98 /**
99 * An implementation of a self growing free list of objects.
100 * Constructors and destructors will be called on the objects.
101 * All memory will be reclaimed when the free list is destroyed, so the free
102 * list must survive longer than you are using any item taken from it.
103 */
104 template<typename T, int growth = 4096/sizeof(T)> class SkFreeList : public SkSL ist<T> {
105 public:
106 SkFreeList() {}
107 ~SkFreeList() {
108 while(!fBlocks.isEmpty()) { SkDELETE(fBlocks.pop()); }
109 }
110 /**
111 * Get an item from the free list.
112 * If the free list has no items, it will grow.
113 * The free list will never shrink, it will use the maximum memory it has
114 * ever reached until destroyed.
115 * The returned item is only valid as long as the free list has not been
116 * destroyed, at that point all memory allocated by grow will have been
117 * reclaimed.
118 * This method is *not* thread safe.
119 */
120 T* pop() {
121 if (this->isEmpty()) { grow(); }
122 return SkSList<T>::pop();
123 }
124 private:
125 /**
126 * The type for a new block of entries for the list.
127 */
128 struct Block {
129 Block() : fNext(0) {}
130 Block* fNext;
131 T entries[growth];
132 };
133 SkSList<Block> fBlocks;
134
135 void grow() {
136 Block* block = SkNEW(Block);
137 fBlocks.push(block);
138 for(int index = 0; index < growth; ++index) {
139 push(&block->entries[index]);
140 }
141 }
142
143 };
14 144
15 /** 145 /**
16 * An QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles 146 * An QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles
tomhudson 2014/03/05 11:56:56 Nit-among-nits: An -> A?
iancottrell 2014/03/05 12:11:16 Done.
17 * in which each internal node has exactly four children. 147 * in which each internal node has exactly four children.
18 * 148 *
19 * For more details see: 149 * For more details see:
20 * 150 *
21 * http://en.wikipedia.org/wiki/Quadtree 151 * http://en.wikipedia.org/wiki/Quadtree
22 */ 152 */
23 class SkQuadTree : public SkBBoxHierarchy { 153 class SkQuadTree : public SkBBoxHierarchy {
24 public: 154 public:
25 SK_DECLARE_INST_COUNT(SkQuadTree) 155 SK_DECLARE_INST_COUNT(SkQuadTree)
26 156
27 /** 157 /**
28 * Create a new QuadTree 158 * Create a new QuadTree
29 */ 159 */
30 static SkQuadTree* Create(const SkIRect& bounds); 160 static SkQuadTree* Create(const SkIRect& bounds);
31 virtual ~SkQuadTree(); 161 virtual ~SkQuadTree();
32 162
33 /** 163 /**
34 * Insert a node, consisting of bounds and a data value into the tree, if we don't immediately 164 * Insert a node, consisting of bounds and a data value into the tree, if we don't immediately
35 * need to use the tree; we may allow the insert to be deferred (this can al low us to bulk-load 165 * need to use the tree; we may allow the insert to be deferred (this can al low us to bulk-load
36 * a large batch of nodes at once, which tends to be faster and produce a be tter tree). 166 * a large batch of nodes at once, which tends to be faster and produce a be tter tree).
37 * @param data The data value 167 * @param data The data value
38 * @param bounds The corresponding bounding box 168 * @param bounds The corresponding bounding box
39 * @param defer Can this insert be deferred? (this may be ignored) 169 * @param defer Can this insert be deferred? (this may be ignored)
40 */ 170 */
41 virtual void insert(void* data, const SkIRect& bounds, bool defer = false) S K_OVERRIDE; 171 virtual void insert(void* data, const SkIRect& bounds, bool defer = false) S K_OVERRIDE;
42 172
43 /** 173 /**
44 * If any inserts have been deferred, this will add them into the tree 174 * If any inserts have been deferred, this will add them into the tree
45 */ 175 */
46 virtual void flushDeferredInserts() SK_OVERRIDE {} 176 virtual void flushDeferredInserts() SK_OVERRIDE;
47 177
48 /** 178 /**
49 * Given a query rectangle, populates the passed-in array with the elements it intersects 179 * Given a query rectangle, populates the passed-in array with the elements it intersects
50 */ 180 */
51 virtual void search(const SkIRect& query, SkTDArray<void*>* results) SK_OVER RIDE; 181 virtual void search(const SkIRect& query, SkTDArray<void*>* results) SK_OVER RIDE;
52 182
53 virtual void clear() SK_OVERRIDE; 183 virtual void clear() SK_OVERRIDE;
54 184
55 /** 185 /**
56 * Gets the depth of the tree structure 186 * Gets the depth of the tree structure
57 */ 187 */
58 virtual int getDepth() const SK_OVERRIDE; 188 virtual int getDepth() const SK_OVERRIDE;
59 189
60 /** 190 /**
61 * This gets the insertion count (rather than the node count) 191 * This gets the insertion count (rather than the node count)
62 */ 192 */
63 virtual int getCount() const SK_OVERRIDE { return fCount; } 193 virtual int getCount() const SK_OVERRIDE { return fEntryCount; }
64 194
65 virtual void rewindInserts() SK_OVERRIDE; 195 virtual void rewindInserts() SK_OVERRIDE;
66 196
67 private: 197 private:
68 class QuadTreeNode; 198 struct Entry {
199 Entry() : fNext(NULL), fData(NULL) {}
200 Entry* fNext;
201 SkIRect fBounds;
202 void* fData;
203 };
204
205 static const int kChildCount = 4;
206
207 struct Node {
208 Node() : fNext(NULL) {
209 for(int index=0; index<kChildCount; ++index) {
tomhudson 2014/03/05 11:56:56 Nit: Skia style has more spaces than you do. (At l
iancottrell 2014/03/05 12:11:16 Done.
210 fChildren[index] = NULL;
211 }
212 }
213 SkSList<Entry> fEntries;
214 SkIRect fBounds;
215 SkIPoint fCenter;
tomhudson 2014/03/05 11:56:56 // Uninitialized until the Node has children (fChi
iancottrell 2014/03/05 12:11:16 Done. Also renamed for clarity.
216 union {
tomhudson 2014/03/05 11:56:56 // A Node is only in a SkFreeList when it is free,
iancottrell 2014/03/05 12:11:16 Done.
217 Node* fNext;
218 Node* fChildren[kChildCount];
219 };
220 };
221
222 SkFreeList<Entry> fAllEntries;
223 SkFreeList<Node> fAllNodes;
tomhudson 2014/03/05 11:56:56 This isn't really *All*Nodes, it's all nodes not c
iancottrell 2014/03/05 12:11:16 Done.
224 int fEntryCount;
225 Node* fRoot;
226 SkSList<Entry> fDeferred;
69 227
70 SkQuadTree(const SkIRect& bounds); 228 SkQuadTree(const SkIRect& bounds);
71 229 Node* pickChild(Node* node, const SkIRect& bounds) const;
72 // This is the count of data elements (rather than total nodes in the tree) 230 void insert(Node* node, Entry* entry);
73 int fCount; 231 void search(Node* node, const SkIRect& query, SkTDArray<void*>* results) con st;
74 232 void clear(Node* node);
75 QuadTreeNode* fRoot; 233 int getDepth(Node* node) const;
76 234
77 typedef SkBBoxHierarchy INHERITED; 235 typedef SkBBoxHierarchy INHERITED;
78 }; 236 };
79 237
80 #endif 238 #endif
OLDNEW
« no previous file with comments | « no previous file | src/core/SkQuadTree.cpp » ('j') | src/core/SkQuadTree.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698