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

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

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

Powered by Google App Engine
This is Rietveld 408576698