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

Side by Side Diff: ui/gfx/geometry/r_tree_unittest.cc

Issue 269513002: readability review for luken (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: ready for next round of feedbac Created 6 years, 7 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
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698