OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "testing/gtest/include/gtest/gtest.h" | 5 #include "testing/gtest/include/gtest/gtest.h" |
6 #include "ui/gfx/geometry/r_tree.h" | 6 #include "ui/gfx/geometry/r_tree.h" |
| 7 #include "ui/gfx/geometry/r_tree_base.h" |
7 #include "ui/gfx/geometry/rect.h" | 8 #include "ui/gfx/geometry/rect.h" |
8 | 9 |
9 namespace gfx { | 10 namespace gfx { |
10 | 11 |
11 class RTreeTest : public ::testing::Test { | 12 class RTreeTest : public ::testing::Test { |
12 protected: | 13 protected: |
13 // Given a pointer to an RTree, traverse it and verify its internal structure | 14 typedef RTree<int> RT; |
14 // is consistent with the RTree semantics. | 15 |
15 void ValidateRTree(RTree* rt) { | 16 // Given a pointer to an RTree, traverse it and verify that its internal |
| 17 // structure is consistent with RTree semantics. |
| 18 void ValidateRTree(RTreeBase* rt) { |
16 // If RTree is empty it should have an empty rectangle. | 19 // If RTree is empty it should have an empty rectangle. |
17 if (!rt->root_->count()) { | 20 if (!rt->root_->count()) { |
18 EXPECT_TRUE(rt->root_->rect().IsEmpty()); | 21 EXPECT_TRUE(rt->root_->rect().IsEmpty()); |
19 EXPECT_EQ(rt->root_->level(), 0); | 22 EXPECT_EQ(rt->root_->level(), 0); |
20 return; | 23 return; |
21 } | 24 } |
22 // Root is allowed to have fewer than min_children_ but never more than | 25 // Root is allowed to have fewer than min_children_ but never more than |
23 // max_children_. | 26 // max_children_. |
24 EXPECT_LE(rt->root_->count(), rt->max_children_); | 27 EXPECT_LE(rt->root_->count(), rt->max_children_); |
25 // The root should never be a record node. | 28 // The root should never be a record node. |
26 EXPECT_GT(rt->root_->level(), -1); | 29 EXPECT_GT(rt->root_->level(), -1); |
27 EXPECT_FALSE(rt->root_->key()); | |
28 // The root should never have a parent pointer. | 30 // The root should never have a parent pointer. |
29 EXPECT_FALSE(rt->root_->parent()); | 31 EXPECT_FALSE(rt->root_->parent()); |
30 // Bounds must be consistent on the root. | 32 // Bounds must be consistent on the root. |
31 CheckBoundsConsistent(rt->root_.get()); | 33 CheckBoundsConsistent(rt->root_.get()); |
32 // We traverse root's children ourselves, so we can avoid asserts about | 34 // We traverse root's children ourselves, so we can avoid asserts about |
33 // root's potential inconsistencies. | 35 // root's potential inconsistencies. |
34 for (size_t i = 0; i < rt->root_->children_.size(); ++i) { | 36 for (size_t i = 0; i < rt->root_->children_.size(); ++i) { |
35 ValidateNode( | 37 ValidateNode( |
36 rt->root_->children_[i], rt->min_children_, rt->max_children_); | 38 rt->root_->children_[i], rt->min_children_, rt->max_children_); |
37 } | 39 } |
38 } | 40 } |
39 | 41 |
40 // Recursive descent method used by ValidateRTree to check each node within | 42 // Recursive descent method used by ValidateRTree to check each node within |
41 // the RTree for consistency with RTree semantics. | 43 // the RTree for consistency with RTree semantics. |
42 void ValidateNode(RTree::Node* node, | 44 void ValidateNode(RTreeBase::NodeBase* node_base, |
43 size_t min_children, | 45 size_t min_children, |
44 size_t max_children) { | 46 size_t max_children) { |
45 // Record nodes have different requirements, handle up front. | 47 if (node_base->level() >= 0) { |
46 if (node->level() == -1) { | 48 RTreeBase::Node* node = static_cast<RTreeBase::Node*>(node_base); |
47 // Record nodes may have no children. | 49 EXPECT_GE(node->count(), min_children); |
48 EXPECT_EQ(node->count(), 0U); | 50 EXPECT_LE(node->count(), max_children); |
49 // They must have an associated non-NULL key. | 51 CheckBoundsConsistent(node); |
50 EXPECT_TRUE(node->key()); | 52 for (size_t i = 0; i < node->children_.size(); ++i) { |
51 // They must always have a parent. | 53 ValidateNode(node->children_[i], min_children, max_children); |
52 EXPECT_TRUE(node->parent()); | 54 } |
53 return; | |
54 } | |
55 // Non-record node, normal expectations apply. | |
56 EXPECT_GE(node->count(), min_children); | |
57 EXPECT_LE(node->count(), max_children); | |
58 EXPECT_EQ(node->key(), 0); | |
59 CheckBoundsConsistent(node); | |
60 for (size_t i = 0; i < node->children_.size(); ++i) { | |
61 ValidateNode(node->children_[i], min_children, max_children); | |
62 } | 55 } |
63 } | 56 } |
64 | 57 |
65 // Check bounds are consistent with children bounds, and other checks | 58 // Check bounds are consistent with children bounds, and other checks |
66 // convenient to do while enumerating the children of node. | 59 // convenient to do while enumerating the children of node. |
67 void CheckBoundsConsistent(RTree::Node* node) { | 60 void CheckBoundsConsistent(RTreeBase::Node* node) { |
68 EXPECT_FALSE(node->rect_.IsEmpty()); | 61 EXPECT_FALSE(node->rect_.IsEmpty()); |
69 Rect check_bounds; | 62 Rect check_bounds; |
70 for (size_t i = 0; i < node->children_.size(); ++i) { | 63 for (size_t i = 0; i < node->children_.size(); ++i) { |
71 RTree::Node* child_node = node->children_[i]; | 64 RTreeBase::NodeBase* child_node = node->children_[i]; |
72 check_bounds.Union(child_node->rect()); | 65 check_bounds.Union(child_node->rect()); |
73 EXPECT_EQ(node->level() - 1, child_node->level()); | 66 EXPECT_EQ(node->level() - 1, child_node->level()); |
74 EXPECT_EQ(node, child_node->parent()); | 67 EXPECT_EQ(node, child_node->parent()); |
75 } | 68 } |
76 EXPECT_EQ(node->rect_, check_bounds); | 69 EXPECT_EQ(node->rect(), check_bounds); |
77 } | 70 } |
78 | 71 |
79 // Adds count squares stacked around the point (0,0) with key equal to width. | 72 // Adds count squares stacked around the point (0,0) with key equal to width. |
80 void AddStackedSquares(RTree* rt, int count) { | 73 void AddStackedSquares(RT* rt, int count) { |
81 for (int i = 1; i <= count; ++i) { | 74 for (int i = 1; i <= count; ++i) { |
82 rt->Insert(Rect(0, 0, i, i), i); | 75 rt->Insert(Rect(0, 0, i, i), i); |
83 ValidateRTree(rt); | 76 ValidateRTree(static_cast<RTreeBase*>(rt)); |
84 } | 77 } |
85 } | 78 } |
86 | 79 |
87 // Given an unordered list of matching keys, verify that it contains all | 80 // Given an unordered list of matching keys, verify that it contains all |
88 // values [1..length] for the length of that list. | 81 // values [1..length] for the length of that list. |
89 void VerifyAllKeys(const base::hash_set<intptr_t>& keys) { | 82 void VerifyAllKeys(const base::hash_set<int>& keys) { |
90 // Verify that the keys are in values [1,count]. | 83 // Verify that the keys are in values [0,count). |
91 for (size_t i = 1; i <= keys.size(); ++i) { | 84 for (size_t i = 1; i <= keys.size(); ++i) { |
92 EXPECT_EQ(keys.count(i), 1U); | 85 EXPECT_EQ(keys.count(i), 1U); |
93 } | 86 } |
94 } | 87 } |
95 | 88 |
96 // Given a node and a rectangle, builds an expanded rectangle list where the | 89 // Given a node and a rectangle, builds an expanded rectangle list where the |
97 // ith element of the rectangle is union of the recangle of the ith child of | 90 // ith element of the rectangle is union of the recangle of the ith child of |
98 // the node and the argument rectangle. | 91 // the node and the argument rectangle. |
99 void BuildExpandedRects(RTree::Node* node, | 92 void BuildExpandedRects(RTreeBase::Node* node, |
100 const Rect& rect, | 93 const Rect& rect, |
101 std::vector<Rect>* expanded_rects) { | 94 std::vector<Rect>* expanded_rects) { |
102 expanded_rects->clear(); | 95 expanded_rects->clear(); |
103 expanded_rects->reserve(node->children_.size()); | 96 expanded_rects->reserve(node->children_.size()); |
104 for (size_t i = 0; i < node->children_.size(); ++i) { | 97 for (size_t i = 0; i < node->children_.size(); ++i) { |
105 Rect expanded_rect(rect); | 98 Rect expanded_rect(rect); |
106 expanded_rect.Union(node->children_[i]->rect_); | 99 expanded_rect.Union(node->children_[i]->rect()); |
107 expanded_rects->push_back(expanded_rect); | 100 expanded_rects->push_back(expanded_rect); |
108 } | 101 } |
109 } | 102 } |
110 }; | 103 }; |
111 | 104 |
112 // An empty RTree should never return Query results, and RTrees should be empty | 105 class RTreeNodeTest : public RTreeTest { |
113 // upon construction. | 106 protected: |
114 TEST_F(RTreeTest, QueryEmptyTree) { | 107 typedef RTreeBase::NodeBase RTreeNodeBase; |
115 RTree rt(2, 10); | 108 typedef RT::Record RTreeRecord; |
116 ValidateRTree(&rt); | 109 typedef RTreeBase::Node RTreeNode; |
117 base::hash_set<intptr_t> results; | 110 typedef RTreeBase::Node::Rects RTreeRects; |
118 Rect test_rect(25, 25); | 111 |
119 rt.Query(test_rect, &results); | 112 // Accessors to private members of RTree::Node. |
120 EXPECT_EQ(results.size(), 0U); | 113 RTreeRecord* record(RTreeNode* node, size_t i) { |
121 ValidateRTree(&rt); | 114 return static_cast<RTreeRecord*>(node->children_[i]); |
122 } | 115 } |
123 | 116 |
124 // Clear should empty the tree, meaning that all queries should not return | 117 // Provides access for tests to private methods of RTree::Node. |
125 // results after. | 118 RTreeNode* NewNodeAtLevel(size_t level) { return new RTreeBase::Node(level); } |
126 TEST_F(RTreeTest, ClearEmptiesTreeOfSingleNode) { | 119 |
127 RTree rt(2, 5); | 120 void NodeRecomputeLocalBounds(RTreeNodeBase* node) { |
128 rt.Insert(Rect(0, 0, 100, 100), 1); | 121 node->RecomputeLocalBounds(); |
129 rt.Clear(); | 122 } |
130 base::hash_set<intptr_t> results; | 123 |
131 Rect test_rect(1, 1); | 124 bool NodeCompareVertical(RTreeNodeBase* a, RTreeNodeBase* b) { |
132 rt.Query(test_rect, &results); | 125 return RTreeBase::Node::CompareVertical(a, b); |
133 EXPECT_EQ(results.size(), 0U); | 126 } |
134 ValidateRTree(&rt); | 127 |
135 } | 128 bool NodeCompareHorizontal(RTreeNodeBase* a, RTreeNodeBase* b) { |
136 | 129 return RTreeBase::Node::CompareHorizontal(a, b); |
137 // Even with a complex internal structure, clear should empty the tree, meaning | 130 } |
138 // that all queries should not return results after. | 131 |
139 TEST_F(RTreeTest, ClearEmptiesTreeOfManyNodes) { | 132 bool NodeCompareCenterDistanceFromParent(RTreeNodeBase* a, RTreeNodeBase* b) { |
140 RTree rt(2, 5); | 133 return RTreeBase::Node::CompareCenterDistanceFromParent(a, b); |
141 AddStackedSquares(&rt, 100); | 134 } |
142 rt.Clear(); | 135 |
143 base::hash_set<intptr_t> results; | 136 int NodeOverlapIncreaseToAdd(RTreeNode* node, |
144 Rect test_rect(1, 1); | 137 const Rect& rect, |
145 rt.Query(test_rect, &results); | 138 size_t candidate, |
146 EXPECT_EQ(results.size(), 0U); | 139 const Rect& expanded_rect) { |
147 ValidateRTree(&rt); | 140 return node->OverlapIncreaseToAdd(rect, candidate, expanded_rect); |
148 } | 141 } |
149 | 142 |
150 // Duplicate inserts should overwrite previous inserts. | 143 void NodeBuildLowBounds(const std::vector<RTreeNodeBase*>& vertical_sort, |
151 TEST_F(RTreeTest, DuplicateInsertsOverwrite) { | 144 const std::vector<RTreeNodeBase*>& horizontal_sort, |
152 RTree rt(2, 5); | 145 RTreeRects* vertical_bounds, |
153 // Add 100 stacked squares, but always with duplicate key of 1. | 146 RTreeRects* horizontal_bounds) { |
154 for (int i = 1; i <= 100; ++i) { | 147 RTreeBase::Node::BuildLowBounds( |
155 rt.Insert(Rect(0, 0, i, i), 1); | 148 vertical_sort, horizontal_sort, vertical_bounds, horizontal_bounds); |
156 ValidateRTree(&rt); | 149 } |
157 } | 150 |
158 base::hash_set<intptr_t> results; | 151 void NodeBuildHighBounds(const std::vector<RTreeNodeBase*>& vertical_sort, |
159 Rect test_rect(1, 1); | 152 const std::vector<RTreeNodeBase*>& horizontal_sort, |
160 rt.Query(test_rect, &results); | 153 RTreeRects* vertical_bounds, |
161 EXPECT_EQ(results.size(), 1U); | 154 RTreeRects* horizontal_bounds) { |
162 EXPECT_EQ(results.count(1), 1U); | 155 RTreeBase::Node::BuildHighBounds( |
163 } | 156 vertical_sort, horizontal_sort, vertical_bounds, horizontal_bounds); |
164 | 157 } |
165 // Call Remove() once on something that's been inserted repeatedly. | 158 |
166 TEST_F(RTreeTest, DuplicateInsertRemove) { | 159 int NodeSmallestMarginSum(size_t start_index, |
167 RTree rt(3, 9); | 160 size_t end_index, |
168 AddStackedSquares(&rt, 25); | 161 const RTreeRects& low_bounds, |
169 for (int i = 1; i <= 100; ++i) { | 162 const RTreeRects& high_bounds) { |
170 rt.Insert(Rect(0, 0, i, i), 26); | 163 return RTreeBase::Node::SmallestMarginSum( |
171 ValidateRTree(&rt); | 164 start_index, end_index, low_bounds, high_bounds); |
172 } | 165 } |
173 rt.Remove(26); | 166 |
174 base::hash_set<intptr_t> results; | 167 size_t NodeChooseSplitIndex(size_t min_children, |
175 Rect test_rect(1, 1); | 168 size_t max_children, |
176 rt.Query(test_rect, &results); | 169 const RTreeRects& low_bounds, |
177 EXPECT_EQ(results.size(), 25U); | 170 const RTreeRects& high_bounds) { |
178 VerifyAllKeys(results); | 171 return RTreeBase::Node::ChooseSplitIndex( |
179 } | 172 min_children, max_children, low_bounds, high_bounds); |
180 | 173 } |
181 // Call Remove() repeatedly on something that's been inserted once. | 174 |
182 TEST_F(RTreeTest, InsertDuplicateRemove) { | 175 RTreeNode* NodeDivideChildren( |
183 RTree rt(7, 15); | 176 RTreeNode* node, |
184 AddStackedSquares(&rt, 101); | 177 const RTreeRects& low_bounds, |
185 for (int i = 0; i < 100; ++i) { | 178 const RTreeRects& high_bounds, |
186 rt.Remove(101); | 179 const std::vector<RTreeNodeBase*>& sorted_children, |
187 ValidateRTree(&rt); | 180 size_t split_index) { |
188 } | 181 return node->DivideChildren( |
189 base::hash_set<intptr_t> results; | 182 low_bounds, high_bounds, sorted_children, split_index); |
190 Rect test_rect(1, 1); | 183 } |
191 rt.Query(test_rect, &results); | 184 |
192 EXPECT_EQ(results.size(), 100U); | 185 RTreeNode* NodeLeastOverlapIncrease(RTreeNode* node, |
193 VerifyAllKeys(results); | 186 const Rect& node_rect, |
194 } | 187 const RTreeRects& expanded_rects) { |
195 | 188 return node->LeastOverlapIncrease(node_rect, expanded_rects); |
196 // Stacked rects should meet all matching queries regardless of nesting. | 189 } |
197 TEST_F(RTreeTest, QueryStackedSquaresNestedHit) { | 190 |
198 RTree rt(2, 5); | 191 RTreeNode* NodeLeastAreaEnlargement(RTreeNode* node, |
199 AddStackedSquares(&rt, 100); | 192 const Rect& node_rect, |
200 base::hash_set<intptr_t> results; | 193 const RTreeRects& expanded_rects) { |
201 Rect test_rect(1, 1); | 194 return node->LeastAreaEnlargement(node_rect, expanded_rects); |
202 rt.Query(test_rect, &results); | 195 } |
203 EXPECT_EQ(results.size(), 100U); | 196 }; |
204 VerifyAllKeys(results); | 197 |
205 } | 198 // RTreeNodeTest -------------------------------------------------------------- |
206 | 199 |
207 // Stacked rects should meet all matching queries when contained completely by | 200 TEST_F(RTreeNodeTest, RemoveNodesForReinsert) { |
208 // the query rectangle. | |
209 TEST_F(RTreeTest, QueryStackedSquaresContainedHit) { | |
210 RTree rt(2, 10); | |
211 AddStackedSquares(&rt, 100); | |
212 base::hash_set<intptr_t> results; | |
213 Rect test_rect(0, 0, 100, 100); | |
214 rt.Query(test_rect, &results); | |
215 EXPECT_EQ(results.size(), 100U); | |
216 VerifyAllKeys(results); | |
217 } | |
218 | |
219 // Stacked rects should miss a missing query when the query has no intersection | |
220 // with the rects. | |
221 TEST_F(RTreeTest, QueryStackedSquaresCompleteMiss) { | |
222 RTree rt(2, 7); | |
223 AddStackedSquares(&rt, 100); | |
224 base::hash_set<intptr_t> results; | |
225 Rect test_rect(150, 150, 100, 100); | |
226 rt.Query(test_rect, &results); | |
227 EXPECT_EQ(results.size(), 0U); | |
228 } | |
229 | |
230 // Removing half the nodes after insertion should still result in a valid tree. | |
231 TEST_F(RTreeTest, RemoveHalfStackedRects) { | |
232 RTree rt(2, 11); | |
233 AddStackedSquares(&rt, 200); | |
234 for (int i = 101; i <= 200; ++i) { | |
235 rt.Remove(i); | |
236 ValidateRTree(&rt); | |
237 } | |
238 base::hash_set<intptr_t> results; | |
239 Rect test_rect(1, 1); | |
240 rt.Query(test_rect, &results); | |
241 EXPECT_EQ(results.size(), 100U); | |
242 VerifyAllKeys(results); | |
243 // Add the nodes back in. | |
244 for (int i = 101; i <= 200; ++i) { | |
245 rt.Insert(Rect(0, 0, i, i), i); | |
246 ValidateRTree(&rt); | |
247 } | |
248 results.clear(); | |
249 rt.Query(test_rect, &results); | |
250 EXPECT_EQ(results.size(), 200U); | |
251 VerifyAllKeys(results); | |
252 } | |
253 | |
254 TEST_F(RTreeTest, InsertNegativeCoordsRect) { | |
255 RTree rt(5, 11); | |
256 for (int i = 1; i <= 100; ++i) { | |
257 rt.Insert(Rect(-i, -i, i, i), (i * 2) - 1); | |
258 ValidateRTree(&rt); | |
259 rt.Insert(Rect(0, 0, i, i), i * 2); | |
260 ValidateRTree(&rt); | |
261 } | |
262 base::hash_set<intptr_t> results; | |
263 Rect test_rect(-1, -1, 2, 2); | |
264 rt.Query(test_rect, &results); | |
265 EXPECT_EQ(results.size(), 200U); | |
266 VerifyAllKeys(results); | |
267 } | |
268 | |
269 TEST_F(RTreeTest, RemoveNegativeCoordsRect) { | |
270 RTree rt(7, 21); | |
271 // Add 100 positive stacked squares. | |
272 AddStackedSquares(&rt, 100); | |
273 // Now add 100 negative stacked squares. | |
274 for (int i = 101; i <= 200; ++i) { | |
275 rt.Insert(Rect(100 - i, 100 - i, i - 100, i - 100), 301 - i); | |
276 ValidateRTree(&rt); | |
277 } | |
278 // Now remove half of the negative squares. | |
279 for (int i = 101; i <= 150; ++i) { | |
280 rt.Remove(301 - i); | |
281 ValidateRTree(&rt); | |
282 } | |
283 // Queries should return 100 positive and 50 negative stacked squares. | |
284 base::hash_set<intptr_t> results; | |
285 Rect test_rect(-1, -1, 2, 2); | |
286 rt.Query(test_rect, &results); | |
287 EXPECT_EQ(results.size(), 150U); | |
288 VerifyAllKeys(results); | |
289 } | |
290 | |
291 TEST_F(RTreeTest, InsertEmptyRectReplacementRemovesKey) { | |
292 RTree rt(10, 31); | |
293 AddStackedSquares(&rt, 50); | |
294 ValidateRTree(&rt); | |
295 | |
296 // Replace last square with empty rect. | |
297 rt.Insert(Rect(), 50); | |
298 ValidateRTree(&rt); | |
299 | |
300 // Now query large area to get all rects in tree. | |
301 base::hash_set<intptr_t> results; | |
302 Rect test_rect(0, 0, 100, 100); | |
303 rt.Query(test_rect, &results); | |
304 | |
305 // Should only be 49 rects in tree. | |
306 EXPECT_EQ(results.size(), 49U); | |
307 VerifyAllKeys(results); | |
308 } | |
309 | |
310 TEST_F(RTreeTest, NodeRemoveNodesForReinsert) { | |
311 // Make a leaf node for testing removal from. | 201 // Make a leaf node for testing removal from. |
312 scoped_ptr<RTree::Node> test_node(new RTree::Node(0)); | 202 scoped_ptr<RTreeNode> test_node(new RTreeNode); |
313 // Build 20 record nodes with rectangle centers going from (1,1) to (20,20) | 203 // Build 20 record nodes with rectangle centers going from (1,1) to (20,20) |
314 for (int i = 1; i <= 20; ++i) { | 204 for (int i = 1; i <= 20; ++i) { |
315 test_node->AddChild(new RTree::Node(Rect(i - 1, i - 1, 2, 2), i)); | 205 test_node->AddChild(scoped_ptr<RTreeNodeBase>( |
| 206 new RTreeRecord(Rect(i - 1, i - 1, 2, 2), i))); |
316 } | 207 } |
317 // Quick verification of the node before removing children. | 208 // Quick verification of the node before removing children. |
318 ValidateNode(test_node.get(), 1U, 20U); | 209 ValidateNode(test_node.get(), 1U, 20U); |
319 // Use a scoped vector to delete all children that get removed from the Node. | 210 // Use a scoped vector to delete all children that get removed from the Node. |
320 ScopedVector<RTree::Node> removals; | 211 ScopedVector<RTreeNodeBase> removals; |
321 test_node->RemoveNodesForReinsert(1, &removals); | 212 test_node->RemoveNodesForReinsert(1, &removals); |
322 // Should have gotten back 1 node pointers. | 213 // Should have gotten back 1 node pointers. |
323 EXPECT_EQ(removals.size(), 1U); | 214 EXPECT_EQ(removals.size(), 1U); |
324 // There should be 19 left in the test_node. | 215 // There should be 19 left in the test_node. |
325 EXPECT_EQ(test_node->count(), 19U); | 216 EXPECT_EQ(test_node->count(), 19U); |
326 // If we fix up the bounds on the test_node, it should verify. | 217 // If we fix up the bounds on the test_node, it should verify. |
327 test_node->RecomputeBoundsNoParents(); | 218 NodeRecomputeLocalBounds(test_node.get()); |
328 ValidateNode(test_node.get(), 2U, 20U); | 219 ValidateNode(test_node.get(), 2U, 20U); |
329 // The node we removed should be node 10, as it was exactly in the center. | 220 // The node we removed should be node 10, as it was exactly in the center. |
330 EXPECT_EQ(removals[0]->key(), 10); | 221 EXPECT_EQ(static_cast<RTreeRecord*>(removals[0])->key(), 10); |
331 | 222 |
332 // Now remove the next 2. | 223 // Now remove the next 2. |
333 removals.clear(); | 224 removals.clear(); |
334 test_node->RemoveNodesForReinsert(2, &removals); | 225 test_node->RemoveNodesForReinsert(2, &removals); |
335 EXPECT_EQ(removals.size(), 2U); | 226 EXPECT_EQ(removals.size(), 2U); |
336 EXPECT_EQ(test_node->count(), 17U); | 227 EXPECT_EQ(test_node->count(), 17U); |
337 test_node->RecomputeBoundsNoParents(); | 228 NodeRecomputeLocalBounds(test_node.get()); |
338 ValidateNode(test_node.get(), 2U, 20U); | 229 ValidateNode(test_node.get(), 2U, 20U); |
339 // Lastly the 2 nodes we should have gotten back are keys 9 and 11, as their | 230 // Lastly the 2 nodes we should have gotten back are keys 9 and 11, as their |
340 // centers were the closest to the center of the node bounding box. | 231 // centers were the closest to the center of the node bounding box. |
341 base::hash_set<intptr_t> results_hash; | 232 base::hash_set<intptr_t> results_hash; |
342 results_hash.insert(removals[0]->key()); | 233 results_hash.insert(static_cast<RTreeRecord*>(removals[0])->key()); |
343 results_hash.insert(removals[1]->key()); | 234 results_hash.insert(static_cast<RTreeRecord*>(removals[1])->key()); |
344 EXPECT_EQ(results_hash.count(9), 1U); | 235 EXPECT_EQ(results_hash.count(9), 1U); |
345 EXPECT_EQ(results_hash.count(11), 1U); | 236 EXPECT_EQ(results_hash.count(11), 1U); |
346 } | 237 } |
347 | 238 |
348 TEST_F(RTreeTest, NodeCompareVertical) { | 239 TEST_F(RTreeNodeTest, CompareVertical) { |
349 // One rect with lower y than another should always sort lower than higher y. | 240 // One rect with lower y than another should always sort lower than higher y. |
350 RTree::Node low(Rect(0, 1, 10, 10), 1); | 241 RTreeRecord low(Rect(0, 1, 10, 10), 1); |
351 RTree::Node middle(Rect(0, 5, 10, 10), 5); | 242 RTreeRecord middle(Rect(0, 5, 10, 10), 5); |
352 EXPECT_TRUE(RTree::Node::CompareVertical(&low, &middle)); | 243 EXPECT_TRUE(NodeCompareVertical(&low, &middle)); |
353 EXPECT_FALSE(RTree::Node::CompareVertical(&middle, &low)); | 244 EXPECT_FALSE(NodeCompareVertical(&middle, &low)); |
354 | 245 |
355 // Try a non-overlapping higher-y rectangle. | 246 // Try a non-overlapping higher-y rectangle. |
356 RTree::Node high(Rect(-10, 20, 10, 1), 10); | 247 RTreeRecord high(Rect(-10, 20, 10, 1), 10); |
357 EXPECT_TRUE(RTree::Node::CompareVertical(&low, &high)); | 248 EXPECT_TRUE(NodeCompareVertical(&low, &high)); |
358 EXPECT_FALSE(RTree::Node::CompareVertical(&high, &low)); | 249 EXPECT_FALSE(NodeCompareVertical(&high, &low)); |
359 | 250 |
360 // Ties are broken by lowest bottom y value. | 251 // Ties are broken by lowest bottom y value. |
361 RTree::Node shorter_tie(Rect(10, 1, 100, 2), 2); | 252 RTreeRecord shorter_tie(Rect(10, 1, 100, 2), 2); |
362 EXPECT_TRUE(RTree::Node::CompareVertical(&shorter_tie, &low)); | 253 EXPECT_TRUE(NodeCompareVertical(&shorter_tie, &low)); |
363 EXPECT_FALSE(RTree::Node::CompareVertical(&low, &shorter_tie)); | 254 EXPECT_FALSE(NodeCompareVertical(&low, &shorter_tie)); |
364 } | 255 } |
365 | 256 |
366 TEST_F(RTreeTest, NodeCompareHorizontal) { | 257 TEST_F(RTreeNodeTest, CompareHorizontal) { |
367 // One rect with lower x than another should always sort lower than higher x. | 258 // One rect with lower x than another should always sort lower than higher x. |
368 RTree::Node low(Rect(1, 0, 10, 10), 1); | 259 RTreeRecord low(Rect(1, 0, 10, 10), 1); |
369 RTree::Node middle(Rect(5, 0, 10, 10), 5); | 260 RTreeRecord middle(Rect(5, 0, 10, 10), 5); |
370 EXPECT_TRUE(RTree::Node::CompareHorizontal(&low, &middle)); | 261 EXPECT_TRUE(NodeCompareHorizontal(&low, &middle)); |
371 EXPECT_FALSE(RTree::Node::CompareHorizontal(&middle, &low)); | 262 EXPECT_FALSE(NodeCompareHorizontal(&middle, &low)); |
372 | 263 |
373 // Try a non-overlapping higher-x rectangle. | 264 // Try a non-overlapping higher-x rectangle. |
374 RTree::Node high(Rect(20, -10, 1, 10), 10); | 265 RTreeRecord high(Rect(20, -10, 1, 10), 10); |
375 EXPECT_TRUE(RTree::Node::CompareHorizontal(&low, &high)); | 266 EXPECT_TRUE(NodeCompareHorizontal(&low, &high)); |
376 EXPECT_FALSE(RTree::Node::CompareHorizontal(&high, &low)); | 267 EXPECT_FALSE(NodeCompareHorizontal(&high, &low)); |
377 | 268 |
378 // Ties are broken by lowest bottom x value. | 269 // Ties are broken by lowest bottom x value. |
379 RTree::Node shorter_tie(Rect(1, 10, 2, 100), 2); | 270 RTreeRecord shorter_tie(Rect(1, 10, 2, 100), 2); |
380 EXPECT_TRUE(RTree::Node::CompareHorizontal(&shorter_tie, &low)); | 271 EXPECT_TRUE(NodeCompareHorizontal(&shorter_tie, &low)); |
381 EXPECT_FALSE(RTree::Node::CompareHorizontal(&low, &shorter_tie)); | 272 EXPECT_FALSE(NodeCompareHorizontal(&low, &shorter_tie)); |
382 } | 273 } |
383 | 274 |
384 TEST_F(RTreeTest, NodeCompareCenterDistanceFromParent) { | 275 TEST_F(RTreeNodeTest, CompareCenterDistanceFromParent) { |
385 // Create a test node we can add children to, for distance comparisons. | 276 // Create a test node we can add children to, for distance comparisons. |
386 scoped_ptr<RTree::Node> parent(new RTree::Node(0)); | 277 scoped_ptr<RTreeNode> parent(new RTreeNode); |
387 | 278 |
388 // Add three children, one each with centers at (0, 0), (10, 10), (-9, -9), | 279 // Add three children, one each with centers at (0, 0), (10, 10), (-9, -9), |
389 // around which a bounding box will be centered at (0, 0) | 280 // around which a bounding box will be centered at (0, 0) |
390 RTree::Node* center_zero = new RTree::Node(Rect(-1, -1, 2, 2), 1); | 281 RTreeRecord* center_zero = new RTreeRecord(Rect(-1, -1, 2, 2), 1); |
391 parent->AddChild(center_zero); | 282 parent->AddChild(scoped_ptr<RTreeNodeBase>(center_zero)); |
392 | 283 |
393 RTree::Node* center_positive = new RTree::Node(Rect(9, 9, 2, 2), 2); | 284 RTreeRecord* center_positive = new RTreeRecord(Rect(9, 9, 2, 2), 2); |
394 parent->AddChild(center_positive); | 285 parent->AddChild(scoped_ptr<RTreeNodeBase>(center_positive)); |
395 | 286 |
396 RTree::Node* center_negative = new RTree::Node(Rect(-10, -10, 2, 2), 3); | 287 RTreeRecord* center_negative = new RTreeRecord(Rect(-10, -10, 2, 2), 3); |
397 parent->AddChild(center_negative); | 288 parent->AddChild(scoped_ptr<RTreeNodeBase>(center_negative)); |
398 | 289 |
399 ValidateNode(parent.get(), 1U, 5U); | 290 ValidateNode(parent.get(), 1U, 5U); |
400 EXPECT_EQ(parent->rect_, Rect(-10, -10, 21, 21)); | 291 EXPECT_EQ(parent->rect(), Rect(-10, -10, 21, 21)); |
401 | 292 |
402 EXPECT_TRUE(RTree::Node::CompareCenterDistanceFromParent(center_zero, | 293 EXPECT_TRUE( |
403 center_positive)); | 294 NodeCompareCenterDistanceFromParent(center_zero, center_positive)); |
404 EXPECT_FALSE(RTree::Node::CompareCenterDistanceFromParent(center_positive, | 295 EXPECT_FALSE( |
405 center_zero)); | 296 NodeCompareCenterDistanceFromParent(center_positive, center_zero)); |
406 | 297 EXPECT_TRUE( |
407 EXPECT_TRUE(RTree::Node::CompareCenterDistanceFromParent(center_zero, | 298 NodeCompareCenterDistanceFromParent(center_zero, center_negative)); |
408 center_negative)); | 299 EXPECT_FALSE( |
409 EXPECT_FALSE(RTree::Node::CompareCenterDistanceFromParent(center_negative, | 300 NodeCompareCenterDistanceFromParent(center_negative, center_zero)); |
410 center_zero)); | 301 EXPECT_TRUE( |
411 | 302 NodeCompareCenterDistanceFromParent(center_negative, center_positive)); |
412 EXPECT_TRUE(RTree::Node::CompareCenterDistanceFromParent(center_negative, | 303 EXPECT_FALSE( |
413 center_positive)); | 304 NodeCompareCenterDistanceFromParent(center_positive, center_negative)); |
414 EXPECT_FALSE(RTree::Node::CompareCenterDistanceFromParent(center_positive, | 305 } |
415 center_negative)); | 306 |
416 } | 307 TEST_F(RTreeNodeTest, OverlapIncreaseToAdd) { |
417 | |
418 TEST_F(RTreeTest, NodeOverlapIncreaseToAdd) { | |
419 // Create a test node with three children, for overlap comparisons. | 308 // Create a test node with three children, for overlap comparisons. |
420 scoped_ptr<RTree::Node> parent(new RTree::Node(0)); | 309 scoped_ptr<RTreeNode> parent(new RTreeNode); |
421 | 310 |
422 // Add three children, each 4 wide and tall, at (0, 0), (3, 3), (6, 6) with | 311 // Add three children, each 4 wide and tall, at (0, 0), (3, 3), (6, 6) with |
423 // overlapping corners. | 312 // overlapping corners. |
424 Rect top(0, 0, 4, 4); | 313 Rect top(0, 0, 4, 4); |
425 parent->AddChild(new RTree::Node(top, 1)); | 314 parent->AddChild(scoped_ptr<RTreeNodeBase>(new RTreeRecord(top, 1))); |
426 Rect middle(3, 3, 4, 4); | 315 Rect middle(3, 3, 4, 4); |
427 parent->AddChild(new RTree::Node(middle, 2)); | 316 parent->AddChild(scoped_ptr<RTreeNodeBase>(new RTreeRecord(middle, 2))); |
428 Rect bottom(6, 6, 4, 4); | 317 Rect bottom(6, 6, 4, 4); |
429 parent->AddChild(new RTree::Node(bottom, 3)); | 318 parent->AddChild(scoped_ptr<RTreeNodeBase>(new RTreeRecord(bottom, 3))); |
430 ValidateNode(parent.get(), 1U, 5U); | 319 ValidateNode(parent.get(), 1U, 5U); |
431 | 320 |
432 // Test a rect in corner. | 321 // Test a rect in corner. |
433 Rect corner(0, 0, 1, 1); | 322 Rect corner(0, 0, 1, 1); |
434 Rect expanded = top; | 323 Rect expanded = top; |
435 expanded.Union(corner); | 324 expanded.Union(corner); |
436 // It should not add any overlap to add this to the first child at (0, 0); | 325 // It should not add any overlap to add this to the first child at (0, 0); |
437 EXPECT_EQ(parent->OverlapIncreaseToAdd(corner, 0, expanded), 0); | 326 EXPECT_EQ(NodeOverlapIncreaseToAdd(parent.get(), corner, 0, expanded), 0); |
438 | 327 |
439 expanded = middle; | 328 expanded = middle; |
440 expanded.Union(corner); | 329 expanded.Union(corner); |
441 // Overlap for middle rectangle should increase from 2 pixels at (3, 3) and | 330 // Overlap for middle rectangle should increase from 2 pixels at (3, 3) and |
442 // (6, 6) to 17 pixels, as it will now cover 4x4 rectangle top, | 331 // (6, 6) to 17 pixels, as it will now cover 4x4 rectangle top, |
443 // so a change of +15 | 332 // so a change of +15 |
444 EXPECT_EQ(parent->OverlapIncreaseToAdd(corner, 1, expanded), 15); | 333 EXPECT_EQ(NodeOverlapIncreaseToAdd(parent.get(), corner, 1, expanded), 15); |
445 | 334 |
446 expanded = bottom; | 335 expanded = bottom; |
447 expanded.Union(corner); | 336 expanded.Union(corner); |
448 // Overlap for bottom rectangle should increase from 1 pixel at (6, 6) to | 337 // Overlap for bottom rectangle should increase from 1 pixel at (6, 6) to |
449 // 32 pixels, as it will now cover both 4x4 rectangles top and middle, | 338 // 32 pixels, as it will now cover both 4x4 rectangles top and middle, |
450 // so a change of 31 | 339 // so a change of 31 |
451 EXPECT_EQ(parent->OverlapIncreaseToAdd(corner, 2, expanded), 31); | 340 EXPECT_EQ(NodeOverlapIncreaseToAdd(parent.get(), corner, 2, expanded), 31); |
452 | 341 |
453 // Test a rect that doesn't overlap with anything, in the far right corner. | 342 // Test a rect that doesn't overlap with anything, in the far right corner. |
454 Rect far_corner(9, 0, 1, 1); | 343 Rect far_corner(9, 0, 1, 1); |
455 expanded = top; | 344 expanded = top; |
456 expanded.Union(far_corner); | 345 expanded.Union(far_corner); |
457 // Overlap of top should go from 1 to 4, as it will now cover the entire first | 346 // Overlap of top should go from 1 to 4, as it will now cover the entire first |
458 // row of pixels in middle. | 347 // row of pixels in middle. |
459 EXPECT_EQ(parent->OverlapIncreaseToAdd(far_corner, 0, expanded), 3); | 348 EXPECT_EQ(NodeOverlapIncreaseToAdd(parent.get(), far_corner, 0, expanded), 3); |
460 | 349 |
461 expanded = middle; | 350 expanded = middle; |
462 expanded.Union(far_corner); | 351 expanded.Union(far_corner); |
463 // Overlap of middle should go from 2 to 8, as it will cover the rightmost 4 | 352 // Overlap of middle should go from 2 to 8, as it will cover the rightmost 4 |
464 // pixels of top and the top 4 pixles of bottom as it expands. | 353 // pixels of top and the top 4 pixles of bottom as it expands. |
465 EXPECT_EQ(parent->OverlapIncreaseToAdd(far_corner, 1, expanded), 6); | 354 EXPECT_EQ(NodeOverlapIncreaseToAdd(parent.get(), far_corner, 1, expanded), 6); |
466 | 355 |
467 expanded = bottom; | 356 expanded = bottom; |
468 expanded.Union(far_corner); | 357 expanded.Union(far_corner); |
469 // Overlap of bottom should go from 1 to 4, as it will now cover the rightmost | 358 // Overlap of bottom should go from 1 to 4, as it will now cover the rightmost |
470 // 4 pixels of middle. | 359 // 4 pixels of middle. |
471 EXPECT_EQ(parent->OverlapIncreaseToAdd(far_corner, 2, expanded), 3); | 360 EXPECT_EQ(NodeOverlapIncreaseToAdd(parent.get(), far_corner, 2, expanded), 3); |
472 } | 361 } |
473 | 362 |
474 TEST_F(RTreeTest, NodeBuildLowBounds) { | 363 TEST_F(RTreeNodeTest, BuildLowBounds) { |
475 ScopedVector<RTree::Node> nodes; | 364 ScopedVector<RTreeNodeBase> records; |
476 nodes.reserve(10); | 365 records.reserve(10); |
477 for (int i = 1; i <= 10; ++i) { | 366 for (int i = 1; i <= 10; ++i) { |
478 nodes.push_back(new RTree::Node(Rect(0, 0, i, i), i)); | 367 records.push_back(new RTreeRecord(Rect(0, 0, i, i), i)); |
479 } | 368 } |
480 std::vector<Rect> vertical_bounds; | 369 RTreeRects vertical_bounds; |
481 std::vector<Rect> horizontal_bounds; | 370 RTreeRects horizontal_bounds; |
482 RTree::Node::BuildLowBounds( | 371 NodeBuildLowBounds( |
483 nodes.get(), nodes.get(), &vertical_bounds, &horizontal_bounds); | 372 records.get(), records.get(), &vertical_bounds, &horizontal_bounds); |
484 for (int i = 0; i < 10; ++i) { | 373 for (int i = 0; i < 10; ++i) { |
485 EXPECT_EQ(vertical_bounds[i], Rect(0, 0, i + 1, i + 1)); | 374 EXPECT_EQ(vertical_bounds[i], Rect(0, 0, i + 1, i + 1)); |
486 EXPECT_EQ(horizontal_bounds[i], Rect(0, 0, i + 1, i + 1)); | 375 EXPECT_EQ(horizontal_bounds[i], Rect(0, 0, i + 1, i + 1)); |
487 } | 376 } |
488 } | 377 } |
489 | 378 |
490 TEST_F(RTreeTest, NodeBuildHighBounds) { | 379 TEST_F(RTreeNodeTest, BuildHighBounds) { |
491 ScopedVector<RTree::Node> nodes; | 380 ScopedVector<RTreeNodeBase> records; |
492 nodes.reserve(25); | 381 records.reserve(25); |
493 for (int i = 0; i < 25; ++i) { | 382 for (int i = 0; i < 25; ++i) { |
494 nodes.push_back(new RTree::Node(Rect(i, i, 25 - i, 25 - i), i)); | 383 records.push_back(new RTreeRecord(Rect(i, i, 25 - i, 25 - i), i)); |
495 } | 384 } |
496 std::vector<Rect> vertical_bounds; | 385 RTreeRects vertical_bounds; |
497 std::vector<Rect> horizontal_bounds; | 386 RTreeRects horizontal_bounds; |
498 RTree::Node::BuildHighBounds( | 387 NodeBuildHighBounds( |
499 nodes.get(), nodes.get(), &vertical_bounds, &horizontal_bounds); | 388 records.get(), records.get(), &vertical_bounds, &horizontal_bounds); |
500 for (int i = 0; i < 25; ++i) { | 389 for (int i = 0; i < 25; ++i) { |
501 EXPECT_EQ(vertical_bounds[i], Rect(i, i, 25 - i, 25 - i)); | 390 EXPECT_EQ(vertical_bounds[i], Rect(i, i, 25 - i, 25 - i)); |
502 EXPECT_EQ(horizontal_bounds[i], Rect(i, i, 25 - i, 25 - i)); | 391 EXPECT_EQ(horizontal_bounds[i], Rect(i, i, 25 - i, 25 - i)); |
503 } | 392 } |
504 } | 393 } |
505 | 394 |
506 TEST_F(RTreeTest, NodeChooseSplitAxisAndIndex) { | 395 TEST_F(RTreeNodeTest, ChooseSplitAxisAndIndex) { |
507 std::vector<Rect> low_vertical_bounds; | 396 RTreeRects low_vertical_bounds; |
508 std::vector<Rect> high_vertical_bounds; | 397 RTreeRects high_vertical_bounds; |
509 std::vector<Rect> low_horizontal_bounds; | 398 RTreeRects low_horizontal_bounds; |
510 std::vector<Rect> high_horizontal_bounds; | 399 RTreeRects high_horizontal_bounds; |
511 // In this test scenario we describe a mirrored, stacked configuration of | 400 // In this test scenario we describe a mirrored, stacked configuration of |
512 // horizontal, 1 pixel high rectangles labeled a-f like this: | 401 // horizontal, 1 pixel high rectangles labeled a-f like this: |
513 // | 402 // |
514 // shape: | v sort: | h sort: | | 403 // shape: | v sort: | h sort: | |
515 // -------+---------+---------+ | 404 // -------+---------+---------+ |
516 // aaaaa | 0 | 0 | | 405 // aaaaa | 0 | 0 | |
517 // bbb | 1 | 2 | | 406 // bbb | 1 | 2 | |
518 // c | 2 | 4 | | 407 // c | 2 | 4 | |
519 // d | 3 | 5 | | 408 // d | 3 | 5 | |
520 // eee | 4 | 3 | | 409 // eee | 4 | 3 | |
(...skipping 14 matching lines...) Expand all Loading... |
535 } | 424 } |
536 | 425 |
537 // High horizontal bounds are hand-calculated. | 426 // High horizontal bounds are hand-calculated. |
538 high_horizontal_bounds.push_back(Rect(0, 0, 5, 6)); | 427 high_horizontal_bounds.push_back(Rect(0, 0, 5, 6)); |
539 high_horizontal_bounds.push_back(Rect(0, 1, 5, 5)); | 428 high_horizontal_bounds.push_back(Rect(0, 1, 5, 5)); |
540 high_horizontal_bounds.push_back(Rect(1, 1, 3, 4)); | 429 high_horizontal_bounds.push_back(Rect(1, 1, 3, 4)); |
541 high_horizontal_bounds.push_back(Rect(1, 2, 3, 3)); | 430 high_horizontal_bounds.push_back(Rect(1, 2, 3, 3)); |
542 high_horizontal_bounds.push_back(Rect(2, 2, 1, 2)); | 431 high_horizontal_bounds.push_back(Rect(2, 2, 1, 2)); |
543 high_horizontal_bounds.push_back(Rect(2, 3, 1, 1)); | 432 high_horizontal_bounds.push_back(Rect(2, 3, 1, 1)); |
544 | 433 |
545 // This should split vertically, right down the middle. | 434 int smallest_vertical_margin = |
546 EXPECT_TRUE(RTree::Node::ChooseSplitAxis(low_vertical_bounds, | 435 NodeSmallestMarginSum(2, 3, low_vertical_bounds, high_vertical_bounds); |
547 high_vertical_bounds, | 436 int smallest_horizontal_margin = NodeSmallestMarginSum( |
548 low_horizontal_bounds, | 437 2, 3, low_horizontal_bounds, high_horizontal_bounds); |
549 high_horizontal_bounds, | 438 EXPECT_LT(smallest_vertical_margin, smallest_horizontal_margin); |
550 2, | 439 |
551 5)); | 440 EXPECT_EQ( |
552 EXPECT_EQ(3U, | 441 3U, |
553 RTree::Node::ChooseSplitIndex( | 442 NodeChooseSplitIndex(2, 5, low_vertical_bounds, high_vertical_bounds)); |
554 2, 5, low_vertical_bounds, high_vertical_bounds)); | |
555 | 443 |
556 // We rotate the shape to test horizontal split axis detection: | 444 // We rotate the shape to test horizontal split axis detection: |
557 // | 445 // |
558 // +--------+ | 446 // +--------+ |
559 // | a f | | 447 // | a f | |
560 // | ab ef | | 448 // | ab ef | |
561 // sort: | abcdef | | 449 // sort: | abcdef | |
562 // | ab ef | | 450 // | ab ef | |
563 // | a f | | 451 // | a f | |
564 // |--------+ | 452 // |--------+ |
(...skipping 23 matching lines...) Expand all Loading... |
588 high_vertical_bounds.push_back(Rect(3, 2, 1, 1)); | 476 high_vertical_bounds.push_back(Rect(3, 2, 1, 1)); |
589 | 477 |
590 // These are already sorted horizontally from left to right. Bounding | 478 // These are already sorted horizontally from left to right. Bounding |
591 // rectangles of these horizontally sorted will be i wide, 5 tall bounding | 479 // rectangles of these horizontally sorted will be i wide, 5 tall bounding |
592 // boxes. | 480 // boxes. |
593 for (int i = 0; i < 6; ++i) { | 481 for (int i = 0; i < 6; ++i) { |
594 low_horizontal_bounds.push_back(Rect(0, 0, i + 1, 5)); | 482 low_horizontal_bounds.push_back(Rect(0, 0, i + 1, 5)); |
595 high_horizontal_bounds.push_back(Rect(i, 0, 6 - i, 5)); | 483 high_horizontal_bounds.push_back(Rect(i, 0, 6 - i, 5)); |
596 } | 484 } |
597 | 485 |
598 // This should split horizontally, right down the middle. | 486 smallest_vertical_margin = |
599 EXPECT_FALSE(RTree::Node::ChooseSplitAxis(low_vertical_bounds, | 487 NodeSmallestMarginSum(2, 3, low_vertical_bounds, high_vertical_bounds); |
600 high_vertical_bounds, | 488 smallest_horizontal_margin = NodeSmallestMarginSum( |
601 low_horizontal_bounds, | 489 2, 3, low_horizontal_bounds, high_horizontal_bounds); |
602 high_horizontal_bounds, | 490 |
603 2, | 491 EXPECT_GT(smallest_vertical_margin, smallest_horizontal_margin); |
604 5)); | 492 |
605 EXPECT_EQ(3U, | 493 EXPECT_EQ(3U, |
606 RTree::Node::ChooseSplitIndex( | 494 NodeChooseSplitIndex( |
607 2, 5, low_horizontal_bounds, high_horizontal_bounds)); | 495 2, 5, low_horizontal_bounds, high_horizontal_bounds)); |
608 } | 496 } |
609 | 497 |
610 TEST_F(RTreeTest, NodeDivideChildren) { | 498 TEST_F(RTreeNodeTest, DivideChildren) { |
611 // Create a test node to split. | 499 // Create a test node to split. |
612 scoped_ptr<RTree::Node> test_node(new RTree::Node(0)); | 500 scoped_ptr<RTreeNode> test_node(new RTreeNode); |
613 std::vector<RTree::Node*> sorted_children; | 501 std::vector<RTreeNodeBase*> sorted_children; |
614 std::vector<Rect> low_bounds; | 502 RTreeRects low_bounds; |
615 std::vector<Rect> high_bounds; | 503 RTreeRects high_bounds; |
616 // Insert 10 record nodes, also inserting them into our children array. | 504 // Insert 10 record nodes, also inserting them into our children array. |
617 for (int i = 1; i <= 10; ++i) { | 505 for (int i = 1; i <= 10; ++i) { |
618 RTree::Node* node = new RTree::Node(Rect(0, 0, i, i), i); | 506 RTreeRecord* record = new RTreeRecord(Rect(0, 0, i, i), i); |
619 test_node->AddChild(node); | 507 test_node->AddChild(scoped_ptr<RTreeNodeBase>(record)); |
620 sorted_children.push_back(node); | 508 sorted_children.push_back(record); |
621 low_bounds.push_back(Rect(0, 0, i, i)); | 509 low_bounds.push_back(Rect(0, 0, i, i)); |
622 high_bounds.push_back(Rect(0, 0, 10, 10)); | 510 high_bounds.push_back(Rect(0, 0, 10, 10)); |
623 } | 511 } |
624 // Split the children in half. | 512 // Split the children in half. |
625 scoped_ptr<RTree::Node> split_node( | 513 scoped_ptr<RTreeNode> split_node(NodeDivideChildren( |
626 test_node->DivideChildren(low_bounds, high_bounds, sorted_children, 5)); | 514 test_node.get(), low_bounds, high_bounds, sorted_children, 5)); |
627 // Both nodes should be valid. | 515 // Both nodes should be valid. |
628 ValidateNode(test_node.get(), 1U, 10U); | 516 ValidateNode(test_node.get(), 1U, 10U); |
629 ValidateNode(split_node.get(), 1U, 10U); | 517 ValidateNode(split_node.get(), 1U, 10U); |
630 // Both nodes should have five children. | 518 // Both nodes should have five children. |
631 EXPECT_EQ(test_node->children_.size(), 5U); | 519 EXPECT_EQ(test_node->count(), 5U); |
632 EXPECT_EQ(split_node->children_.size(), 5U); | 520 EXPECT_EQ(split_node->count(), 5U); |
633 // Test node should have children 1-5, split node should have children 6-10. | 521 // Test node should have children 1-5, split node should have children 6-10. |
634 for (int i = 0; i < 5; ++i) { | 522 for (int i = 0; i < 5; ++i) { |
635 EXPECT_EQ(test_node->children_[i]->key(), i + 1); | 523 EXPECT_EQ(record(test_node.get(), i)->key(), i + 1); |
636 EXPECT_EQ(split_node->children_[i]->key(), i + 6); | 524 EXPECT_EQ(record(split_node.get(), i)->key(), i + 6); |
637 } | 525 } |
638 } | 526 } |
639 | 527 |
640 TEST_F(RTreeTest, NodeRemoveChildNoOrphans) { | 528 TEST_F(RTreeNodeTest, RemoveChildNoOrphans) { |
641 scoped_ptr<RTree::Node> test_parent(new RTree::Node(0)); | 529 scoped_ptr<RTreeNode> test_parent(new RTreeNode); |
642 scoped_ptr<RTree::Node> child_one(new RTree::Node(Rect(0, 0, 1, 1), 1)); | 530 RTreeRecord* child_one(new RTreeRecord(Rect(0, 0, 1, 1), 1)); |
643 scoped_ptr<RTree::Node> child_two(new RTree::Node(Rect(0, 0, 2, 2), 2)); | 531 RTreeRecord* child_two(new RTreeRecord(Rect(0, 0, 2, 2), 2)); |
644 scoped_ptr<RTree::Node> child_three(new RTree::Node(Rect(0, 0, 3, 3), 3)); | 532 RTreeRecord* child_three(new RTreeRecord(Rect(0, 0, 3, 3), 3)); |
645 test_parent->AddChild(child_one.get()); | 533 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(child_one)); |
646 test_parent->AddChild(child_two.get()); | 534 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(child_two)); |
647 test_parent->AddChild(child_three.get()); | 535 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(child_three)); |
648 ValidateNode(test_parent.get(), 1U, 5U); | 536 ValidateNode(test_parent.get(), 1U, 5U); |
649 // Remove the middle node. | 537 // Remove the middle node. |
650 ScopedVector<RTree::Node> orphans; | 538 ScopedVector<RTreeNodeBase> orphans; |
651 EXPECT_EQ(test_parent->RemoveChild(child_two.get(), &orphans), 2U); | 539 EXPECT_EQ(test_parent->RemoveChild(child_two, &orphans), 2U); |
652 EXPECT_EQ(orphans.size(), 0U); | 540 EXPECT_EQ(orphans.size(), 0U); |
653 EXPECT_EQ(test_parent->count(), 2U); | 541 EXPECT_EQ(test_parent->count(), 2U); |
654 test_parent->RecomputeBoundsNoParents(); | 542 NodeRecomputeLocalBounds(test_parent.get()); |
655 ValidateNode(test_parent.get(), 1U, 5U); | 543 ValidateNode(test_parent.get(), 1U, 5U); |
| 544 delete child_two; |
656 // Remove the end node. | 545 // Remove the end node. |
657 EXPECT_EQ(test_parent->RemoveChild(child_three.get(), &orphans), 1U); | 546 EXPECT_EQ(test_parent->RemoveChild(child_three, &orphans), 1U); |
658 EXPECT_EQ(orphans.size(), 0U); | 547 EXPECT_EQ(orphans.size(), 0U); |
659 EXPECT_EQ(test_parent->count(), 1U); | 548 EXPECT_EQ(test_parent->count(), 1U); |
660 test_parent->RecomputeBoundsNoParents(); | 549 NodeRecomputeLocalBounds(test_parent.get()); |
661 ValidateNode(test_parent.get(), 1U, 5U); | 550 ValidateNode(test_parent.get(), 1U, 5U); |
| 551 delete child_three; |
662 // Remove the first node. | 552 // Remove the first node. |
663 EXPECT_EQ(test_parent->RemoveChild(child_one.get(), &orphans), 0U); | 553 EXPECT_EQ(test_parent->RemoveChild(child_one, &orphans), 0U); |
664 EXPECT_EQ(orphans.size(), 0U); | 554 EXPECT_EQ(orphans.size(), 0U); |
665 EXPECT_EQ(test_parent->count(), 0U); | 555 EXPECT_EQ(test_parent->count(), 0U); |
| 556 delete child_one; |
666 } | 557 } |
667 | 558 |
668 TEST_F(RTreeTest, NodeRemoveChildOrphans) { | 559 TEST_F(RTreeNodeTest, RemoveChildOrphans) { |
669 // Build flattened binary tree of Nodes 4 deep, from the record nodes up. | 560 // Build flattened binary tree of Nodes 4 deep, from the record nodes up. |
670 ScopedVector<RTree::Node> nodes; | 561 ScopedVector<RTreeNode> nodes; |
671 nodes.resize(15); | 562 ScopedVector<RTreeRecord> records; |
672 // Indicies 7 through 15 are record nodes. | 563 nodes.resize(7); |
673 for (int i = 7; i < 15; ++i) { | 564 records.reserve(8); |
674 nodes[i] = new RTree::Node(Rect(0, 0, i, i), i); | 565 for (int i = 0; i < 8; ++i) { |
| 566 records.push_back(new RTreeRecord(Rect(0, 0, i, i), i + 1)); |
675 } | 567 } |
| 568 |
676 // Nodes 3 through 6 are level 0 (leaves) and get 2 record nodes each. | 569 // Nodes 3 through 6 are level 0 (leaves) and get 2 record nodes each. |
| 570 int record_counter = 0; |
677 for (int i = 3; i < 7; ++i) { | 571 for (int i = 3; i < 7; ++i) { |
678 nodes[i] = new RTree::Node(0); | 572 RTreeNode* node = new RTreeNode; |
679 nodes[i]->AddChild(nodes[(i * 2) + 1]); | 573 node->AddChild(scoped_ptr<RTreeNodeBase>(records[record_counter++])); |
680 nodes[i]->AddChild(nodes[(i * 2) + 2]); | 574 node->AddChild(scoped_ptr<RTreeNodeBase>(records[record_counter++])); |
| 575 nodes[i] = node; |
681 } | 576 } |
| 577 |
682 // Nodes 1 and 2 are level 1 and get 2 leaves each. | 578 // Nodes 1 and 2 are level 1 and get 2 leaves each. |
683 for (int i = 1; i < 3; ++i) { | 579 for (int i = 1; i < 3; ++i) { |
684 nodes[i] = new RTree::Node(1); | 580 RTreeNode* node = NewNodeAtLevel(1); |
685 nodes[i]->AddChild(nodes[(i * 2) + 1]); | 581 node->AddChild(scoped_ptr<RTreeNodeBase>(nodes[(i * 2) + 1])); |
686 nodes[i]->AddChild(nodes[(i * 2) + 2]); | 582 node->AddChild(scoped_ptr<RTreeNodeBase>(nodes[(i * 2) + 2])); |
| 583 nodes[i] = node; |
687 } | 584 } |
688 // Node 0 is level 2 and gets 2 childen. | 585 |
689 nodes[0] = new RTree::Node(2); | 586 // Node 0 is level 2 and gets 2 children. |
690 nodes[0]->AddChild(nodes[1]); | 587 RTreeNode* node_zero = NewNodeAtLevel(2); |
691 nodes[0]->AddChild(nodes[2]); | 588 node_zero->AddChild(scoped_ptr<RTreeNodeBase>(nodes[1])); |
| 589 node_zero->AddChild(scoped_ptr<RTreeNodeBase>(nodes[2])); |
| 590 nodes[0] = node_zero; |
| 591 |
692 // This should now be a valid node structure. | 592 // This should now be a valid node structure. |
693 ValidateNode(nodes[0], 2U, 2U); | 593 ValidateNode(nodes[0], 2U, 2U); |
694 | 594 |
695 // Now remove the level 0 nodes, so we get the record nodes as orphans. | 595 // Now remove the level 0 nodes, so we get the record nodes as orphans. |
696 ScopedVector<RTree::Node> orphans; | 596 ScopedVector<RTreeNodeBase> orphans; |
697 EXPECT_EQ(nodes[1]->RemoveChild(nodes[3], &orphans), 1U); | 597 EXPECT_EQ(nodes[1]->RemoveChild(nodes[3], &orphans), 1U); |
698 EXPECT_EQ(nodes[1]->RemoveChild(nodes[4], &orphans), 0U); | 598 EXPECT_EQ(nodes[1]->RemoveChild(nodes[4], &orphans), 0U); |
699 EXPECT_EQ(nodes[2]->RemoveChild(nodes[5], &orphans), 1U); | 599 EXPECT_EQ(nodes[2]->RemoveChild(nodes[5], &orphans), 1U); |
700 EXPECT_EQ(nodes[2]->RemoveChild(nodes[6], &orphans), 0U); | 600 EXPECT_EQ(nodes[2]->RemoveChild(nodes[6], &orphans), 0U); |
701 | 601 |
702 // Orphans should be nodes 7 through 15 in order. | 602 // Orphans should be all 8 records but no order guarantee. |
703 EXPECT_EQ(orphans.size(), 8U); | 603 EXPECT_EQ(orphans.size(), 8U); |
704 for (int i = 0; i < 8; ++i) { | 604 for (int i = 0; i < 8; i++) { |
705 EXPECT_EQ(orphans[i], nodes[i + 7]); | 605 RTreeNodeBase* base = records[i]; |
| 606 for (ScopedVector<RTreeNodeBase>::iterator it = orphans.begin(); |
| 607 it != orphans.end(); |
| 608 ++it) { |
| 609 if (*it == base) { |
| 610 orphans.weak_erase(it); |
| 611 break; |
| 612 } |
| 613 } |
706 } | 614 } |
| 615 EXPECT_EQ(orphans.size(), 0U); |
707 | 616 |
708 // Now we remove nodes 1 and 2 from the root, expecting no further orphans. | 617 // Now we remove nodes 1 and 2 from the root, expecting no further orphans. |
709 // This prevents a crash due to double-delete on test exit, as no node should | 618 // This prevents a crash due to double-delete on test exit, as no node should |
710 // own any other node right now. | 619 // own any other node right now. |
711 EXPECT_EQ(nodes[0]->RemoveChild(nodes[1], &orphans), 1U); | 620 EXPECT_EQ(nodes[0]->RemoveChild(nodes[1], &orphans), 1U); |
712 EXPECT_EQ(orphans.size(), 8U); | 621 EXPECT_EQ(orphans.size(), 0U); |
713 EXPECT_EQ(nodes[0]->RemoveChild(nodes[2], &orphans), 0U); | 622 EXPECT_EQ(nodes[0]->RemoveChild(nodes[2], &orphans), 0U); |
714 EXPECT_EQ(orphans.size(), 8U); | 623 EXPECT_EQ(orphans.size(), 0U); |
715 | |
716 // Prevent double-delete of nodes by both nodes and orphans. | |
717 orphans.weak_clear(); | |
718 } | 624 } |
719 | 625 |
720 TEST_F(RTreeTest, NodeRemoveAndReturnLastChild) { | 626 TEST_F(RTreeNodeTest, RemoveAndReturnLastChild) { |
721 scoped_ptr<RTree::Node> test_parent(new RTree::Node(0)); | 627 scoped_ptr<RTreeNode> test_parent(new RTreeNode); |
722 scoped_ptr<RTree::Node> child_one(new RTree::Node(Rect(0, 0, 1, 1), 1)); | 628 RTreeRecord* child_one(new RTreeRecord(Rect(0, 0, 1, 1), 1)); |
723 scoped_ptr<RTree::Node> child_two(new RTree::Node(Rect(0, 0, 2, 2), 2)); | 629 RTreeRecord* child_two(new RTreeRecord(Rect(0, 0, 2, 2), 2)); |
724 scoped_ptr<RTree::Node> child_three(new RTree::Node(Rect(0, 0, 3, 3), 3)); | 630 RTreeRecord* child_three(new RTreeRecord(Rect(0, 0, 3, 3), 3)); |
725 test_parent->AddChild(child_one.get()); | 631 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(child_one)); |
726 test_parent->AddChild(child_two.get()); | 632 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(child_two)); |
727 test_parent->AddChild(child_three.get()); | 633 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(child_three)); |
728 ValidateNode(test_parent.get(), 1U, 5U); | 634 ValidateNode(test_parent.get(), 1U, 5U); |
729 | 635 |
730 EXPECT_EQ(test_parent->RemoveAndReturnLastChild().release(), | 636 EXPECT_EQ(test_parent->RemoveAndReturnLastChild().release(), child_three); |
731 child_three.get()); | |
732 EXPECT_EQ(test_parent->count(), 2U); | 637 EXPECT_EQ(test_parent->count(), 2U); |
733 test_parent->RecomputeBoundsNoParents(); | 638 NodeRecomputeLocalBounds(test_parent.get()); |
734 ValidateNode(test_parent.get(), 1U, 5U); | 639 ValidateNode(test_parent.get(), 1U, 5U); |
| 640 delete child_three; |
735 | 641 |
736 EXPECT_EQ(test_parent->RemoveAndReturnLastChild().release(), child_two.get()); | 642 EXPECT_EQ(test_parent->RemoveAndReturnLastChild().release(), child_two); |
737 EXPECT_EQ(test_parent->count(), 1U); | 643 EXPECT_EQ(test_parent->count(), 1U); |
738 test_parent->RecomputeBoundsNoParents(); | 644 NodeRecomputeLocalBounds(test_parent.get()); |
739 ValidateNode(test_parent.get(), 1U, 5U); | 645 ValidateNode(test_parent.get(), 1U, 5U); |
| 646 delete child_two; |
740 | 647 |
741 EXPECT_EQ(test_parent->RemoveAndReturnLastChild().release(), child_one.get()); | 648 EXPECT_EQ(test_parent->RemoveAndReturnLastChild().release(), child_one); |
742 EXPECT_EQ(test_parent->count(), 0U); | 649 EXPECT_EQ(test_parent->count(), 0U); |
| 650 delete child_one; |
743 } | 651 } |
744 | 652 |
745 TEST_F(RTreeTest, NodeLeastOverlapIncrease) { | 653 TEST_F(RTreeNodeTest, LeastOverlapIncrease) { |
746 scoped_ptr<RTree::Node> test_parent(new RTree::Node(0)); | 654 scoped_ptr<RTreeNode> test_parent(NewNodeAtLevel(1)); |
747 // Construct 4 nodes with 1x2 retangles spaced horizontally 1 pixel apart, or: | 655 // Construct 4 nodes with 1x2 rects spaced horizontally 1 pixel apart, or: |
748 // | 656 // |
749 // a b c d | 657 // a b c d |
750 // a b c d | 658 // a b c d |
751 // | 659 // |
752 for (int i = 0; i < 4; ++i) { | 660 for (int i = 0; i < 4; ++i) { |
753 test_parent->AddChild(new RTree::Node(Rect(i * 2, 0, 1, 2), i + 1)); | 661 RTreeNode* node = new RTreeNode; |
| 662 RTreeRecord* record = new RTreeRecord(Rect(i * 2, 0, 1, 2), i + 1); |
| 663 node->AddChild(scoped_ptr<RTreeNodeBase>(record)); |
| 664 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(node)); |
754 } | 665 } |
755 | 666 |
756 ValidateNode(test_parent.get(), 1U, 5U); | 667 ValidateNode(test_parent.get(), 1U, 5U); |
757 | 668 |
758 // Test rect at (7, 0) should require minimum overlap on the part of the | 669 // Test rect at (7, 0) should require minimum overlap on the part of the |
759 // fourth rectangle to add: | 670 // fourth rectangle to add: |
760 // | 671 // |
761 // a b c dT | 672 // a b c dT |
762 // a b c d | 673 // a b c d |
763 // | 674 // |
764 Rect test_rect_far(7, 0, 1, 1); | 675 Rect test_rect_far(7, 0, 1, 1); |
765 std::vector<Rect> expanded_rects; | 676 RTreeRects expanded_rects; |
766 BuildExpandedRects(test_parent.get(), test_rect_far, &expanded_rects); | 677 BuildExpandedRects(test_parent.get(), test_rect_far, &expanded_rects); |
767 RTree::Node* result = | 678 RTreeNode* result = NodeLeastOverlapIncrease( |
768 test_parent->LeastOverlapIncrease(test_rect_far, expanded_rects); | 679 test_parent.get(), test_rect_far, expanded_rects); |
769 EXPECT_EQ(result->key(), 4); | 680 EXPECT_EQ(record(result, 0)->key(), 4); |
770 | 681 |
771 // Test rect covering the bottom half of all children should be a 4-way tie, | 682 // Test rect covering the bottom half of all children should be a 4-way tie, |
772 // so LeastOverlapIncrease should return NULL: | 683 // so LeastOverlapIncrease should return NULL: |
773 // | 684 // |
774 // a b c d | 685 // a b c d |
775 // TTTTTTT | 686 // TTTTTTT |
776 // | 687 // |
777 Rect test_rect_tie(0, 1, 7, 1); | 688 Rect test_rect_tie(0, 1, 7, 1); |
778 BuildExpandedRects(test_parent.get(), test_rect_tie, &expanded_rects); | 689 BuildExpandedRects(test_parent.get(), test_rect_tie, &expanded_rects); |
779 result = test_parent->LeastOverlapIncrease(test_rect_tie, expanded_rects); | 690 result = NodeLeastOverlapIncrease( |
| 691 test_parent.get(), test_rect_tie, expanded_rects); |
780 EXPECT_TRUE(result == NULL); | 692 EXPECT_TRUE(result == NULL); |
781 | 693 |
782 // Test rect completely inside c should return the third rectangle: | 694 // Test rect completely inside c should return the third rectangle: |
783 // | 695 // |
784 // a b T d | 696 // a b T d |
785 // a b c d | 697 // a b c d |
786 // | 698 // |
787 Rect test_rect_inside(4, 0, 1, 1); | 699 Rect test_rect_inside(4, 0, 1, 1); |
788 BuildExpandedRects(test_parent.get(), test_rect_inside, &expanded_rects); | 700 BuildExpandedRects(test_parent.get(), test_rect_inside, &expanded_rects); |
789 result = test_parent->LeastOverlapIncrease(test_rect_inside, expanded_rects); | 701 result = NodeLeastOverlapIncrease( |
790 EXPECT_EQ(result->key(), 3); | 702 test_parent.get(), test_rect_inside, expanded_rects); |
| 703 EXPECT_EQ(record(result, 0)->key(), 3); |
791 | 704 |
792 // Add a rectangle that overlaps completely with rectangle c, to test | 705 // Add a rectangle that overlaps completely with rectangle c, to test |
793 // when there is a tie between two completely contained rectangles: | 706 // when there is a tie between two completely contained rectangles: |
794 // | 707 // |
795 // a b Ted | 708 // a b Ted |
796 // a b eed | 709 // a b eed |
797 // | 710 // |
798 test_parent->AddChild(new RTree::Node(Rect(4, 0, 2, 2), 9)); | 711 RTreeNode* record_parent = new RTreeNode; |
| 712 record_parent->AddChild( |
| 713 scoped_ptr<RTreeNodeBase>(new RTreeRecord(Rect(4, 0, 2, 2), 9))); |
| 714 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(record_parent)); |
799 BuildExpandedRects(test_parent.get(), test_rect_inside, &expanded_rects); | 715 BuildExpandedRects(test_parent.get(), test_rect_inside, &expanded_rects); |
800 result = test_parent->LeastOverlapIncrease(test_rect_inside, expanded_rects); | 716 result = NodeLeastOverlapIncrease( |
| 717 test_parent.get(), test_rect_inside, expanded_rects); |
801 EXPECT_TRUE(result == NULL); | 718 EXPECT_TRUE(result == NULL); |
802 } | 719 } |
803 | 720 |
804 TEST_F(RTreeTest, NodeLeastAreaEnlargement) { | 721 TEST_F(RTreeNodeTest, LeastAreaEnlargement) { |
805 scoped_ptr<RTree::Node> test_parent(new RTree::Node(0)); | 722 scoped_ptr<RTreeNode> test_parent(NewNodeAtLevel(1)); |
806 // Construct 4 nodes in a cross-hairs style configuration: | 723 // Construct 4 nodes in a cross-hairs style configuration: |
807 // | 724 // |
808 // a | 725 // a |
809 // b c | 726 // b c |
810 // d | 727 // d |
811 // | 728 // |
812 test_parent->AddChild(new RTree::Node(Rect(1, 0, 1, 1), 1)); | 729 RTreeNode* node = new RTreeNode; |
813 test_parent->AddChild(new RTree::Node(Rect(0, 1, 1, 1), 2)); | 730 node->AddChild( |
814 test_parent->AddChild(new RTree::Node(Rect(2, 1, 1, 1), 3)); | 731 scoped_ptr<RTreeNodeBase>(new RTreeRecord(Rect(1, 0, 1, 1), 1))); |
815 test_parent->AddChild(new RTree::Node(Rect(1, 2, 1, 1), 4)); | 732 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(node)); |
| 733 node = new RTreeNode; |
| 734 node->AddChild( |
| 735 scoped_ptr<RTreeNodeBase>(new RTreeRecord(Rect(0, 1, 1, 1), 2))); |
| 736 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(node)); |
| 737 node = new RTreeNode; |
| 738 node->AddChild( |
| 739 scoped_ptr<RTreeNodeBase>(new RTreeRecord(Rect(2, 1, 1, 1), 3))); |
| 740 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(node)); |
| 741 node = new RTreeNode; |
| 742 node->AddChild( |
| 743 scoped_ptr<RTreeNodeBase>(new RTreeRecord(Rect(1, 2, 1, 1), 4))); |
| 744 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(node)); |
816 | 745 |
817 ValidateNode(test_parent.get(), 1U, 5U); | 746 ValidateNode(test_parent.get(), 1U, 5U); |
818 | 747 |
819 // Test rect at (1, 3) should require minimum area to add to Node d: | 748 // Test rect at (1, 3) should require minimum area to add to Node d: |
820 // | 749 // |
821 // a | 750 // a |
822 // b c | 751 // b c |
823 // d | 752 // d |
824 // T | 753 // T |
825 // | 754 // |
826 Rect test_rect_below(1, 3, 1, 1); | 755 Rect test_rect_below(1, 3, 1, 1); |
827 std::vector<Rect> expanded_rects; | 756 RTreeRects expanded_rects; |
828 BuildExpandedRects(test_parent.get(), test_rect_below, &expanded_rects); | 757 BuildExpandedRects(test_parent.get(), test_rect_below, &expanded_rects); |
829 RTree::Node* result = | 758 RTreeNode* result = NodeLeastAreaEnlargement( |
830 test_parent->LeastAreaEnlargement(test_rect_below, expanded_rects); | 759 test_parent.get(), test_rect_below, expanded_rects); |
831 EXPECT_EQ(result->key(), 4); | 760 EXPECT_EQ(record(result, 0)->key(), 4); |
832 | 761 |
833 // Test rect completely inside b should require minimum area to add to Node b: | 762 // Test rect completely inside b should require minimum area to add to Node b: |
834 // | 763 // |
835 // a | 764 // a |
836 // T c | 765 // T c |
837 // d | 766 // d |
838 // | 767 // |
839 Rect test_rect_inside(0, 1, 1, 1); | 768 Rect test_rect_inside(0, 1, 1, 1); |
840 BuildExpandedRects(test_parent.get(), test_rect_inside, &expanded_rects); | 769 BuildExpandedRects(test_parent.get(), test_rect_inside, &expanded_rects); |
841 result = test_parent->LeastAreaEnlargement(test_rect_inside, expanded_rects); | 770 result = NodeLeastAreaEnlargement( |
842 EXPECT_EQ(result->key(), 2); | 771 test_parent.get(), test_rect_inside, expanded_rects); |
| 772 EXPECT_EQ(record(result, 0)->key(), 2); |
843 | 773 |
844 // Add e at (0, 1) to overlap b and c, to test tie-breaking: | 774 // Add e at (0, 1) to overlap b and c, to test tie-breaking: |
845 // | 775 // |
846 // a | 776 // a |
847 // eee | 777 // eee |
848 // d | 778 // d |
849 // | 779 // |
850 test_parent->AddChild(new RTree::Node(Rect(0, 1, 3, 1), 7)); | 780 node = new RTreeNode; |
| 781 node->AddChild( |
| 782 scoped_ptr<RTreeNodeBase>(new RTreeRecord(Rect(0, 1, 3, 1), 7))); |
| 783 test_parent->AddChild(scoped_ptr<RTreeNodeBase>(node)); |
851 | 784 |
852 ValidateNode(test_parent.get(), 1U, 5U); | 785 ValidateNode(test_parent.get(), 1U, 5U); |
853 | 786 |
854 // Test rect at (3, 1) should tie between c and e, but c has smaller area so | 787 // Test rect at (3, 1) should tie between c and e, but c has smaller area so |
855 // the algorithm should select c: | 788 // the algorithm should select c: |
856 // | 789 // |
857 // | 790 // |
858 // a | 791 // a |
859 // eeeT | 792 // eeeT |
860 // d | 793 // d |
861 // | 794 // |
862 Rect test_rect_tie_breaker(3, 1, 1, 1); | 795 Rect test_rect_tie_breaker(3, 1, 1, 1); |
863 BuildExpandedRects(test_parent.get(), test_rect_tie_breaker, &expanded_rects); | 796 BuildExpandedRects(test_parent.get(), test_rect_tie_breaker, &expanded_rects); |
864 result = | 797 result = NodeLeastAreaEnlargement( |
865 test_parent->LeastAreaEnlargement(test_rect_tie_breaker, expanded_rects); | 798 test_parent.get(), test_rect_tie_breaker, expanded_rects); |
866 EXPECT_EQ(result->key(), 3); | 799 EXPECT_EQ(record(result, 0)->key(), 3); |
| 800 } |
| 801 |
| 802 // RTreeTest ------------------------------------------------------------------ |
| 803 |
| 804 // An empty RTree should never return Query results, and RTrees should be empty |
| 805 // upon construction. |
| 806 TEST_F(RTreeTest, QueryEmptyTree) { |
| 807 RT rt(2, 10); |
| 808 ValidateRTree(&rt); |
| 809 base::hash_set<int> results; |
| 810 Rect test_rect(25, 25); |
| 811 rt.Query(test_rect, &results); |
| 812 EXPECT_EQ(results.size(), 0U); |
| 813 ValidateRTree(&rt); |
| 814 } |
| 815 |
| 816 // Clear should empty the tree, meaning that all queries should not return |
| 817 // results after. |
| 818 TEST_F(RTreeTest, ClearEmptiesTreeOfSingleNode) { |
| 819 RT rt(2, 5); |
| 820 rt.Insert(Rect(0, 0, 100, 100), 1); |
| 821 rt.Clear(); |
| 822 base::hash_set<int> results; |
| 823 Rect test_rect(1, 1); |
| 824 rt.Query(test_rect, &results); |
| 825 EXPECT_EQ(results.size(), 0U); |
| 826 ValidateRTree(&rt); |
| 827 } |
| 828 |
| 829 // Even with a complex internal structure, clear should empty the tree, meaning |
| 830 // that all queries should not return results after. |
| 831 TEST_F(RTreeTest, ClearEmptiesTreeOfManyNodes) { |
| 832 RT rt(2, 5); |
| 833 AddStackedSquares(&rt, 100); |
| 834 rt.Clear(); |
| 835 base::hash_set<int> results; |
| 836 Rect test_rect(1, 1); |
| 837 rt.Query(test_rect, &results); |
| 838 EXPECT_EQ(results.size(), 0U); |
| 839 ValidateRTree(&rt); |
| 840 } |
| 841 |
| 842 // Duplicate inserts should overwrite previous inserts. |
| 843 TEST_F(RTreeTest, DuplicateInsertsOverwrite) { |
| 844 RT rt(2, 5); |
| 845 // Add 100 stacked squares, but always with duplicate key of 0. |
| 846 for (int i = 1; i <= 100; ++i) { |
| 847 rt.Insert(Rect(0, 0, i, i), 0); |
| 848 ValidateRTree(&rt); |
| 849 } |
| 850 base::hash_set<int> results; |
| 851 Rect test_rect(1, 1); |
| 852 rt.Query(test_rect, &results); |
| 853 EXPECT_EQ(results.size(), 1U); |
| 854 EXPECT_EQ(results.count(0), 1U); |
| 855 } |
| 856 |
| 857 // Call Remove() once on something that's been inserted repeatedly. |
| 858 TEST_F(RTreeTest, DuplicateInsertRemove) { |
| 859 RT rt(3, 9); |
| 860 AddStackedSquares(&rt, 25); |
| 861 for (int i = 1; i <= 100; ++i) { |
| 862 rt.Insert(Rect(0, 0, i, i), 26); |
| 863 ValidateRTree(&rt); |
| 864 } |
| 865 rt.Remove(26); |
| 866 base::hash_set<int> results; |
| 867 Rect test_rect(1, 1); |
| 868 rt.Query(test_rect, &results); |
| 869 EXPECT_EQ(results.size(), 25U); |
| 870 VerifyAllKeys(results); |
| 871 } |
| 872 |
| 873 // Call Remove() repeatedly on something that's been inserted once. |
| 874 TEST_F(RTreeTest, InsertDuplicateRemove) { |
| 875 RT rt(7, 15); |
| 876 AddStackedSquares(&rt, 101); |
| 877 for (int i = 0; i < 100; ++i) { |
| 878 rt.Remove(101); |
| 879 ValidateRTree(&rt); |
| 880 } |
| 881 base::hash_set<int> results; |
| 882 Rect test_rect(1, 1); |
| 883 rt.Query(test_rect, &results); |
| 884 EXPECT_EQ(results.size(), 100U); |
| 885 VerifyAllKeys(results); |
| 886 } |
| 887 |
| 888 // Stacked rects should meet all matching queries regardless of nesting. |
| 889 TEST_F(RTreeTest, QueryStackedSquaresNestedHit) { |
| 890 RT rt(2, 5); |
| 891 AddStackedSquares(&rt, 100); |
| 892 base::hash_set<int> results; |
| 893 Rect test_rect(1, 1); |
| 894 rt.Query(test_rect, &results); |
| 895 EXPECT_EQ(results.size(), 100U); |
| 896 VerifyAllKeys(results); |
| 897 } |
| 898 |
| 899 // Stacked rects should meet all matching queries when contained completely by |
| 900 // the query rectangle. |
| 901 TEST_F(RTreeTest, QueryStackedSquaresContainedHit) { |
| 902 RT rt(2, 10); |
| 903 AddStackedSquares(&rt, 100); |
| 904 base::hash_set<int> results; |
| 905 Rect test_rect(0, 0, 100, 100); |
| 906 rt.Query(test_rect, &results); |
| 907 EXPECT_EQ(results.size(), 100U); |
| 908 VerifyAllKeys(results); |
| 909 } |
| 910 |
| 911 // Stacked rects should miss a missing query when the query has no intersection |
| 912 // with the rects. |
| 913 TEST_F(RTreeTest, QueryStackedSquaresCompleteMiss) { |
| 914 RT rt(2, 7); |
| 915 AddStackedSquares(&rt, 100); |
| 916 base::hash_set<int> results; |
| 917 Rect test_rect(150, 150, 100, 100); |
| 918 rt.Query(test_rect, &results); |
| 919 EXPECT_EQ(results.size(), 0U); |
| 920 } |
| 921 |
| 922 // Removing half the nodes after insertion should still result in a valid tree. |
| 923 TEST_F(RTreeTest, RemoveHalfStackedRects) { |
| 924 RT rt(2, 11); |
| 925 AddStackedSquares(&rt, 200); |
| 926 for (int i = 101; i <= 200; ++i) { |
| 927 rt.Remove(i); |
| 928 ValidateRTree(&rt); |
| 929 } |
| 930 base::hash_set<int> results; |
| 931 Rect test_rect(1, 1); |
| 932 rt.Query(test_rect, &results); |
| 933 EXPECT_EQ(results.size(), 100U); |
| 934 VerifyAllKeys(results); |
| 935 // Add the nodes back in. |
| 936 for (int i = 101; i <= 200; ++i) { |
| 937 rt.Insert(Rect(0, 0, i, i), i); |
| 938 ValidateRTree(&rt); |
| 939 } |
| 940 results.clear(); |
| 941 rt.Query(test_rect, &results); |
| 942 EXPECT_EQ(results.size(), 200U); |
| 943 VerifyAllKeys(results); |
| 944 } |
| 945 |
| 946 TEST_F(RTreeTest, InsertNegativeCoordsRect) { |
| 947 RT rt(5, 11); |
| 948 for (int i = 1; i <= 100; ++i) { |
| 949 rt.Insert(Rect(-i, -i, i, i), (i * 2) - 1); |
| 950 ValidateRTree(&rt); |
| 951 rt.Insert(Rect(0, 0, i, i), i * 2); |
| 952 ValidateRTree(&rt); |
| 953 } |
| 954 base::hash_set<int> results; |
| 955 Rect test_rect(-1, -1, 2, 2); |
| 956 rt.Query(test_rect, &results); |
| 957 EXPECT_EQ(results.size(), 200U); |
| 958 VerifyAllKeys(results); |
| 959 } |
| 960 |
| 961 TEST_F(RTreeTest, RemoveNegativeCoordsRect) { |
| 962 RT rt(7, 21); |
| 963 // Add 100 positive stacked squares. |
| 964 AddStackedSquares(&rt, 100); |
| 965 // Now add 100 negative stacked squares. |
| 966 for (int i = 101; i <= 200; ++i) { |
| 967 rt.Insert(Rect(100 - i, 100 - i, i - 100, i - 100), 301 - i); |
| 968 ValidateRTree(&rt); |
| 969 } |
| 970 // Now remove half of the negative squares. |
| 971 for (int i = 101; i <= 150; ++i) { |
| 972 rt.Remove(301 - i); |
| 973 ValidateRTree(&rt); |
| 974 } |
| 975 // Queries should return 100 positive and 50 negative stacked squares. |
| 976 base::hash_set<int> results; |
| 977 Rect test_rect(-1, -1, 2, 2); |
| 978 rt.Query(test_rect, &results); |
| 979 EXPECT_EQ(results.size(), 150U); |
| 980 VerifyAllKeys(results); |
| 981 } |
| 982 |
| 983 TEST_F(RTreeTest, InsertEmptyRectReplacementRemovesKey) { |
| 984 RT rt(10, 31); |
| 985 AddStackedSquares(&rt, 50); |
| 986 ValidateRTree(&rt); |
| 987 |
| 988 // Replace last square with empty rect. |
| 989 rt.Insert(Rect(), 50); |
| 990 ValidateRTree(&rt); |
| 991 |
| 992 // Now query large area to get all rects in tree. |
| 993 base::hash_set<int> results; |
| 994 Rect test_rect(0, 0, 100, 100); |
| 995 rt.Query(test_rect, &results); |
| 996 |
| 997 // Should only be 49 rects in tree. |
| 998 EXPECT_EQ(results.size(), 49U); |
| 999 VerifyAllKeys(results); |
867 } | 1000 } |
868 | 1001 |
869 } // namespace gfx | 1002 } // namespace gfx |
OLD | NEW |