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

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: Reveiw fixes, renaming 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 14
robertphillips 2014/03/05 13:08:53 Might be worth mirroring SkTInternalList.h
iancottrell 2014/03/07 15:06:34 Done.
15 /** 15 /**
16 * An QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles 16 * An implementation of an intrusive singly linked list.
17 * The type T must have a field fNext that is visible to the list.
18 * The list does not maintain ownership of any of its elements, or ever delete
19 * them.
20 * The fNext must be null on any object handed to push, and will be NULL when
21 * returned from pop. It is free to use while the object is not in the a list.
22 */
23 template<typename T> class SkSList {
24 public:
25 SkSList() : fHead(NULL), fCount(0) {}
26
27 /**
28 * Push an item onto the head of the list.
29 * This method is *not* thread safe.
30 */
31 void push(T* entry) {
32 SkASSERT(entry->fNext == NULL);
33 entry->fNext = fHead;
34 fHead = entry;
35 ++fCount;
36 }
37
38 /**
39 * Takes all the items from another list.
reed1 2014/03/05 14:33:01 Are they added to the head or the tail of this lis
iancottrell 2014/03/07 15:06:34 Done.
40 */
41 void takeAll(SkSList<T>& other) {
reed1 2014/03/05 14:33:01 typically in Skia if the argument is changed, we p
iancottrell 2014/03/07 15:06:34 Done.
42 if (isEmpty()) {
43 swap(other);
44 return;
45 }
46 while(!other.isEmpty()) {
47 push(other.pop());
48 }
49 }
50
51 /**
52 * Pop an item from the head of the list.
53 * Returns NULL if the list is empty.
54 * This method is *not* thread safe.
55 */
56 T* pop() {
57 if (fHead == NULL) {
58 return NULL;
59 }
60 T* result = fHead;
61 fHead = result->fNext;
62 result->fNext = NULL;
63 --fCount;
64 return result;
65 }
66
67 T* head() {
68 return fHead;
69 }
70
71 /**
72 * Returns true if the list has no elements.
73 */
74 bool isEmpty() {
reed1 2014/03/05 14:33:01 const
iancottrell 2014/03/07 15:06:34 Done.
75 return fHead == NULL;
reed1 2014/03/05 14:33:01 tiny nit: Skia tries to be paranoid, and writes th
iancottrell 2014/03/07 15:06:34 Done.
76 }
77
78 /**
79 * Swaps the contents of this list with another one.
80 */
81 void swap(SkSList<T>& other) {
82 SkTSwap(fHead, other.fHead);
83 SkTSwap(fCount, other.fCount);
84 }
85
86 /**
87 * Returns the count of elements in the list.
88 */
89 int getCount() {
reed1 2014/03/05 14:33:01 const
iancottrell 2014/03/07 15:06:34 Done.
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 };
144
145 /**
146 * A QuadTree implementation. In short, it is a tree containing a hierarchy of b ounding rectangles
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
reed1 2014/03/05 14:33:01 What is the bounds parameter? Can the factory ever
iancottrell 2014/03/07 15:06:34 To be honest, I have no idea why this code has a f
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) {
210 fChildren[index] = NULL;
211 }
212 }
213 SkSList<Entry> fEntries;
214 SkIRect fBounds;
215 SkIPoint fSplitPoint; // Only valid if the node has children.
216 union { // Unioned only to save space
217 Node* fNext; // Used when in a free list, where it has no children.
218 Node* fChildren[kChildCount];
219 };
220 };
221
222 SkFreeList<Entry> fFreeEntries;
223 SkFreeList<Node> fFreeNodes;
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