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

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

Issue 269513002: readability review for luken (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 "ui/gfx/geometry/r_tree.h" 5 #include "ui/gfx/geometry/r_tree.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 11
12 namespace { 12 namespace {
Peter Kasting 2014/05/02 18:04:57 Nit: Totally optional, but in files that include d
luken 2014/05/08 00:00:08 Done.
13 13
14 // Returns the center coordinates of the given rectangle. 14 // Returns the center coordinates of the given rectangle.
Peter Kasting 2014/05/02 18:04:57 Nit: Comment not necessary (we can tell this from
luken 2014/05/08 00:00:08 Done.
15 gfx::Vector2d CenterOfRect(const gfx::Rect& rect) { 15 gfx::Vector2d CenterOfRect(const gfx::Rect& rect) {
Peter Kasting 2014/05/02 18:04:57 It seems odd that this returns a vector instead of
luken 2014/05/08 00:00:08 Done.
16 return rect.OffsetFromOrigin() + 16 return rect.OffsetFromOrigin() +
17 gfx::Vector2d(rect.width() / 2, rect.height() / 2); 17 gfx::Vector2d(rect.width() / 2, rect.height() / 2);
18 } 18 }
19
19 } 20 }
20 21
21 namespace gfx { 22 namespace gfx {
22 23
23 RTree::Node::Node(int level) : level_(level), parent_(NULL), key_(0) { 24 RTree::Node::Node(int level) : level_(level), parent_(NULL), key_(0) {
24 } 25 }
25 26
26 RTree::Node::Node(const Rect& rect, intptr_t key) 27 RTree::Node::Node(const Rect& rect, intptr_t key)
27 : rect_(rect), level_(-1), parent_(NULL), key_(key) { 28 : rect_(rect), level_(-1), parent_(NULL), key_(key) {
Peter Kasting 2014/05/02 18:04:57 From http://google-styleguide.googlecode.com/svn/t
luken 2014/05/08 00:00:08 clang format wants to move them all back to one li
28 } 29 }
29 30
30 RTree::Node::~Node() { 31 RTree::Node::~Node() {
31 Clear(); 32 Clear();
32 } 33 }
33 34
34 void RTree::Node::Clear() { 35 void RTree::Node::Clear() {
35 // Iterate through children and delete them all. 36 // Iterate through children and delete them all.
Peter Kasting 2014/05/02 18:04:57 Documenting what ScopedVector::clear() does doesn'
luken 2014/05/08 00:00:08 Done.
36 children_.clear(); 37 children_.clear();
37 key_ = 0; 38 key_ = 0;
38 } 39 }
39 40
40 void RTree::Node::Query(const Rect& query_rect, 41 void RTree::Node::Query(const Rect& query_rect,
41 base::hash_set<intptr_t>* matches_out) const { 42 base::hash_set<intptr_t>* matches_out) const {
Peter Kasting 2014/05/02 18:04:57 You should probably add to the comment in the head
luken 2014/05/08 00:00:08 Done.
42 // Check own bounding box for intersection, can cull all children if no 43 // Check own bounding box for intersection, can cull all children if no
43 // intersection. 44 // intersection.
44 if (!rect_.Intersects(query_rect)) { 45 if (!rect_.Intersects(query_rect)) {
Peter Kasting 2014/05/02 18:04:57 This style is legal, but in Chrome code we normall
luken 2014/05/08 00:00:08 Done.
45 return; 46 return;
46 } 47 }
47 48
48 // Conversely if we are completely contained within the query rect we can 49 // Conversely if we are completely contained within the query rect we can
49 // confidently skip all bounds checks for ourselves and all our children. 50 // confidently skip all bounds checks for ourselves and all our children.
50 if (query_rect.Contains(rect_)) { 51 if (query_rect.Contains(rect_)) {
51 GetAllValues(matches_out); 52 GetAllValues(matches_out);
52 return; 53 return;
53 } 54 }
54 55
55 // We intersect the query rect but we are not are not contained within it. 56 // We intersect the query rect but we are not are not contained within it.
56 // If we are a record node, then add our record value. Otherwise we must 57 // If we are a record node, then add our record value. Otherwise we must
57 // query each of our children in turn. 58 // query each of our children in turn.
58 if (key_) { 59 if (key_) {
59 DCHECK_EQ(level_, -1); 60 DCHECK_EQ(level_, -1);
Peter Kasting 2014/05/02 18:04:57 Nit: (expected, actual) for DCHECK_EQ and DCHECK_N
luken 2014/05/08 00:00:08 I will remove needless DCHECKs and fix ordering on
60 matches_out->insert(key_); 61 matches_out->insert(key_);
61 } else { 62 } else {
62 for (size_t i = 0; i < children_.size(); ++i) { 63 for (size_t i = 0; i < children_.size(); ++i) {
Peter Kasting 2014/05/02 18:04:57 Prefer using iterators over indexes (primarily in
luken 2014/05/08 00:00:08 Done.
63 // Sanity-check our children. 64 // Sanity-check our children.
64 Node* node = children_[i]; 65 Node* node = children_[i];
Peter Kasting 2014/05/02 18:04:57 This really should be a const Node* (or, if using
luken 2014/05/08 00:00:08 Done.
65 DCHECK_EQ(node->parent_, this); 66 DCHECK_EQ(node->parent_, this);
66 DCHECK_EQ(level_ - 1, node->level_); 67 DCHECK_EQ(level_ - 1, node->level_);
Peter Kasting 2014/05/02 18:04:57 Again, these first two checks don't seem to have a
luken 2014/05/08 00:00:08 Done.
67 DCHECK(rect_.Contains(node->rect_)); 68 DCHECK(rect_.Contains(node->rect_));
68 node->Query(query_rect, matches_out); 69 node->Query(query_rect, matches_out);
69 } 70 }
70 } 71 }
71 } 72 }
72 73
73 void RTree::Node::RecomputeBounds() { 74 void RTree::Node::RecomputeBounds() {
74 RecomputeBoundsNoParents(); 75 RecomputeBoundsNoParents();
75 // Recompute our parent's bounds recursively up to the root. 76 // Recompute our parent's bounds recursively up to the root.
76 if (parent_) { 77 if (parent_) {
77 parent_->RecomputeBounds(); 78 parent_->RecomputeBounds();
78 } 79 }
79 } 80 }
80 81
81 void RTree::Node::RemoveNodesForReinsert(size_t number_to_remove, 82 void RTree::Node::RemoveNodesForReinsert(size_t number_to_remove,
82 ScopedVector<Node>* nodes) { 83 ScopedVector<Node>* nodes) {
83 DCHECK_GE(children_.size(), number_to_remove); 84 DCHECK_GE(children_.size(), number_to_remove);
Peter Kasting 2014/05/02 18:04:57 For DCHECK_GE() and similar, write in "natural" or
luken 2014/05/08 00:00:08 Done.
84 85
85 // Sort our children by their distance from the center of their rectangles to 86 // Sort our children by their distance from the center of their rectangles to
86 // the center of our bounding rectangle. 87 // the center of our bounding rectangle.
Peter Kasting 2014/05/02 18:04:57 Nit: This comment (and others below, see subsequen
luken 2014/05/08 00:00:08 Done.
87 std::sort(children_.begin(), 88 std::sort(children_.begin(),
88 children_.end(), 89 children_.end(),
89 &RTree::Node::CompareCenterDistanceFromParent); 90 &RTree::Node::CompareCenterDistanceFromParent);
90 91
91 // Add lowest distance nodes from our children list to the returned vector. 92 // Add lowest distance nodes from our children list to the returned vector.
Peter Kasting 2014/05/02 18:04:57 Nit: If you say "Move the lowest-distance children
luken 2014/05/08 00:00:08 Done.
92 nodes->insert( 93 nodes->insert(
93 nodes->end(), children_.begin(), children_.begin() + number_to_remove); 94 nodes->end(), children_.begin(), children_.begin() + number_to_remove);
Peter Kasting 2014/05/02 18:04:57 Nit: This is clang-format's preferred formatting h
luken 2014/05/08 00:00:08 Done.
94 // Remove those same nodes from our list, without deleting them. 95 // Remove those same nodes from our list, without deleting them.
95 children_.weak_erase(children_.begin(), children_.begin() + number_to_remove); 96 children_.weak_erase(children_.begin(), children_.begin() + number_to_remove);
96 } 97 }
97 98
98 size_t RTree::Node::RemoveChild(Node* child_node, ScopedVector<Node>* orphans) { 99 size_t RTree::Node::RemoveChild(Node* child_node, ScopedVector<Node>* orphans) {
99 // Should actually be one of our children. 100 // Should actually be one of our children.
100 DCHECK_EQ(child_node->parent_, this); 101 DCHECK_EQ(child_node->parent_, this);
101 102
102 // Add children of child_node to the orphans vector. 103 // Add children of child_node to the orphans vector.
Peter Kasting 2014/05/02 18:04:57 Nit: Same comments as above... I won't make notes
luken 2014/05/08 00:00:08 Done.
103 orphans->insert(orphans->end(), 104 orphans->insert(orphans->end(),
104 child_node->children_.begin(), 105 child_node->children_.begin(),
105 child_node->children_.end()); 106 child_node->children_.end());
106 // Remove without deletion those children from the child_node vector. 107 // Remove without deletion those children from the child_node vector.
107 child_node->children_.weak_clear(); 108 child_node->children_.weak_clear();
108 109
109 // Find an iterator to this Node in our own children_ vector. 110 // Find an iterator to this Node in our own children_ vector.
110 ScopedVector<Node>::iterator child_it = children_.end(); 111 ScopedVector<Node>::iterator child_it = children_.end();
111 for (size_t i = 0; i < children_.size(); ++i) { 112 for (size_t i = 0; i < children_.size(); ++i) {
112 if (children_[i] == child_node) { 113 if (children_[i] == child_node) {
113 child_it = children_.begin() + i; 114 child_it = children_.begin() + i;
Peter Kasting 2014/05/02 18:04:57 Nit: Again, using an iterator for the loop above w
luken 2014/05/08 00:00:08 Done.
114 break; 115 break;
115 } 116 }
116 } 117 }
117 // Should have found the pointer in our children_ vector. 118 // Should have found the pointer in our children_ vector.
118 DCHECK(child_it != children_.end()); 119 DCHECK(child_it != children_.end());
119 // Remove without deleting the child node from our children_ vector. 120 // Remove without deleting the child node from our children_ vector.
120 children_.weak_erase(child_it); 121 children_.weak_erase(child_it);
121 122
122 return children_.size(); 123 return children_.size();
123 } 124 }
124 125
125 scoped_ptr<RTree::Node> RTree::Node::RemoveAndReturnLastChild() { 126 scoped_ptr<RTree::Node> RTree::Node::RemoveAndReturnLastChild() {
126 if (!children_.size()) 127 if (!children_.size())
Peter Kasting 2014/05/02 18:04:57 Use empty() instead of !size().
luken 2014/05/08 00:00:08 Done.
127 return scoped_ptr<Node>(); 128 return scoped_ptr<Node>();
128 129
129 scoped_ptr<Node> last_child(children_[children_.size() - 1]); 130 scoped_ptr<Node> last_child(children_[children_.size() - 1]);
Peter Kasting 2014/05/02 18:04:57 Use .back() instead of [children_.size() - 1].
luken 2014/05/08 00:00:08 Done.
130 DCHECK_EQ(last_child->parent_, this); 131 DCHECK_EQ(last_child->parent_, this);
Peter Kasting 2014/05/02 18:04:57 This DCHECK is arguable -- at least it's not total
luken 2014/05/08 00:00:08 Done.
131 children_.weak_erase(children_.begin() + children_.size() - 1); 132 children_.weak_erase(children_.begin() + children_.size() - 1);
Peter Kasting 2014/05/02 18:04:57 Use children_.end() - 1 instead of children_.begin
luken 2014/05/08 00:00:08 Done.
132 // Invalidate parent, as this child may even become the new root. 133 // Invalidate parent, as this child may even become the new root.
Peter Kasting 2014/05/02 18:04:57 I'd have expected the |parent_| field to get clear
luken 2014/05/08 00:00:08 Done.
133 last_child->parent_ = NULL; 134 last_child->parent_ = NULL;
134 return last_child.Pass(); 135 return last_child.Pass();
135 } 136 }
136 137
137 // Uses the R*-Tree algorithm CHOOSELEAF proposed by Beckmann et al. 138 // Uses the R*-Tree algorithm CHOOSELEAF proposed by Beckmann et al.
138 RTree::Node* RTree::Node::ChooseSubtree(Node* node) { 139 RTree::Node* RTree::Node::ChooseSubtree(Node* node) {
139 // Should never be called on a record node. 140 // Should never be called on a record node.
140 DCHECK(!key_); 141 DCHECK(!key_);
Peter Kasting 2014/05/02 18:04:57 The second DCHECK seems sufficient. This method d
luken 2014/05/08 00:00:08 Done.
141 DCHECK(level_ >= 0); 142 DCHECK(level_ >= 0);
Peter Kasting 2014/05/02 18:04:57 DCHECK_GE
luken 2014/05/08 00:00:08 Done.
142 DCHECK(node); 143 DCHECK(node);
Peter Kasting 2014/05/02 18:04:57 Nit: Consider putting this DCHECK above the commen
luken 2014/05/08 00:00:08 Done.
143 144
144 // If we are a parent of nodes on the provided node level, we are done. 145 // If we are a parent of nodes on the provided node level, we are done.
Peter Kasting 2014/05/02 18:04:57 What if we're _at_ the node's level, or below it?
luken 2014/05/08 00:00:08 It does, I corrected the DCHECK above to account,
145 if (level_ == node->level_ + 1) 146 if (level_ == node->level_ + 1)
146 return this; 147 return this;
147 148
148 // We are an internal node, and thus guaranteed to have children. 149 // We are an internal node, and thus guaranteed to have children.
149 DCHECK_GT(children_.size(), 0U); 150 DCHECK_GT(children_.size(), 0U);
Peter Kasting 2014/05/02 18:04:57 Use !empty(). But really, I don't see how this fu
luken 2014/05/08 00:00:08 Done.
150 151
151 // Iterate over all children to find best candidate for insertion. 152 // Iterate over all children to find best candidate for insertion.
Peter Kasting 2014/05/02 18:04:57 This method doesn't iterate, so this comment doesn
luken 2014/05/08 00:00:08 Done.
152 Node* best_candidate = NULL; 153 Node* best_candidate = NULL;
Peter Kasting 2014/05/02 18:04:57 From http://google-styleguide.googlecode.com/svn/t
luken 2014/05/08 00:00:08 Done.
153 154
154 // Precompute a vector of expanded rects, used both by LeastOverlapIncrease 155 // Precompute a vector of expanded rects, used both by LeastOverlapIncrease
155 // and LeastAreaEnlargement. 156 // and LeastAreaEnlargement.
156 std::vector<Rect> expanded_rects; 157 std::vector<Rect> expanded_rects;
157 expanded_rects.reserve(children_.size()); 158 expanded_rects.reserve(children_.size());
158 for (size_t i = 0; i < children_.size(); ++i) { 159 for (size_t i = 0; i < children_.size(); ++i) {
159 Rect expanded_rect(node->rect_); 160 Rect expanded_rect(node->rect_);
160 expanded_rect.Union(children_[i]->rect_); 161 expanded_rect.Union(children_[i]->rect_);
161 expanded_rects.push_back(expanded_rect); 162 expanded_rects.push_back(expanded_rect);
Peter Kasting 2014/05/02 18:04:57 This can be simplified using the helpers in ui/gfx
luken 2014/05/08 00:00:08 Done.
162 } 163 }
163 164
164 // For parents of leaf nodes, we pick the node that will cause the least 165 // For parents of leaf nodes, we pick the node that will cause the least
165 // increase in overlap by the addition of this new node. This may detect a 166 // increase in overlap by the addition of this new node. This may detect a
166 // tie, in which case it will return NULL. 167 // tie, in which case it will return NULL.
167 if (level_ == 1) 168 if (level_ == 1)
168 best_candidate = LeastOverlapIncrease(node->rect_, expanded_rects); 169 best_candidate = LeastOverlapIncrease(node->rect_, expanded_rects);
169 170
170 // For non-parents of leaf nodes, or for parents of leaf nodes with ties in 171 // For non-parents of leaf nodes, or for parents of leaf nodes with ties in
171 // overlap increase, we choose the subtree with least area enlargement caused 172 // overlap increase, we choose the subtree with least area enlargement caused
172 // by the addition of the new node. 173 // by the addition of the new node.
173 if (!best_candidate) 174 if (!best_candidate)
174 best_candidate = LeastAreaEnlargement(node->rect_, expanded_rects); 175 best_candidate = LeastAreaEnlargement(node->rect_, expanded_rects);
175 176
176 DCHECK(best_candidate); 177 DCHECK(best_candidate);
177 return best_candidate->ChooseSubtree(node); 178 return best_candidate->ChooseSubtree(node);
178 } 179 }
179 180
180 RTree::Node* RTree::Node::LeastAreaEnlargement( 181 RTree::Node* RTree::Node::LeastAreaEnlargement(
Peter Kasting 2014/05/02 18:04:57 Keep .cc function definition order the same as the
181 const Rect& node_rect, 182 const Rect& node_rect,
182 const std::vector<Rect>& expanded_rects) { 183 const std::vector<Rect>& expanded_rects) {
183 Node* best_node = NULL; 184 Node* best_node = NULL;
184 int least_area_enlargement = std::numeric_limits<int>::max(); 185 int least_area_enlargement = std::numeric_limits<int>::max();
Peter Kasting 2014/05/02 18:04:57 Nit: I suggest this: Node* best_node = children
luken 2014/05/08 00:00:08 I got rid of the INT_MAX. I'd prefer to keep with
Peter Kasting 2014/05/08 18:08:21 Ah, sorry, I think I missed that. Using an index
luken 2014/05/14 00:12:04 Done.
185 for (size_t i = 0; i < children_.size(); ++i) { 186 for (size_t i = 0; i < children_.size(); ++i) {
186 Node* candidate_node = children_[i]; 187 Node* candidate_node = children_[i];
187 int area_change = expanded_rects[i].size().GetArea() - 188 int area_change = expanded_rects[i].size().GetArea() -
Peter Kasting 2014/05/02 18:04:57 Can area change be negative? (I assume not.) May
luken 2014/05/08 00:00:08 You are correct, by definition of Union area chang
188 candidate_node->rect_.size().GetArea(); 189 candidate_node->rect_.size().GetArea();
Peter Kasting 2014/05/02 18:04:57 Nit: I believe this should be indented 4 rather th
luken 2014/05/08 00:00:08 Done.
189 if (area_change < least_area_enlargement) { 190 if (area_change < least_area_enlargement) {
190 best_node = candidate_node; 191 best_node = candidate_node;
191 least_area_enlargement = area_change; 192 least_area_enlargement = area_change;
192 } else if (area_change == least_area_enlargement) { 193 } else if (area_change == least_area_enlargement) {
193 // Ties are broken by choosing entry with least area. 194 // Ties are broken by choosing entry with least area.
Peter Kasting 2014/05/02 18:04:57 Nit Add articles ("the" two places)
luken 2014/05/08 00:00:08 Done.
194 DCHECK(best_node); 195 DCHECK(best_node);
195 if (candidate_node->rect_.size().GetArea() < 196 if (candidate_node->rect_.size().GetArea() <
196 best_node->rect_.size().GetArea()) { 197 best_node->rect_.size().GetArea()) {
197 best_node = candidate_node; 198 best_node = candidate_node;
198 } 199 }
199 } 200 }
200 } 201 }
201 202
202 DCHECK(best_node); 203 DCHECK(best_node);
Peter Kasting 2014/05/02 18:04:57 If |children_| is empty, we'll fail this. It seem
luken 2014/05/08 00:00:08 Done.
203 return best_node; 204 return best_node;
204 } 205 }
205 206
206 RTree::Node* RTree::Node::LeastOverlapIncrease( 207 RTree::Node* RTree::Node::LeastOverlapIncrease(
207 const Rect& node_rect, 208 const Rect& node_rect,
208 const std::vector<Rect>& expanded_rects) { 209 const std::vector<Rect>& expanded_rects) {
209 Node* best_node = NULL; 210 Node* best_node = NULL;
210 bool has_tied_node = false; 211 bool has_tied_node = false;
Peter Kasting 2014/05/02 18:04:57 You don't actually need this if you follow the sam
luken 2014/05/08 00:00:08 Done.
211 int least_overlap_increase = std::numeric_limits<int>::max(); 212 int least_overlap_increase = std::numeric_limits<int>::max();
212 for (size_t i = 0; i < children_.size(); ++i) { 213 for (size_t i = 0; i < children_.size(); ++i) {
213 int overlap_increase = 214 int overlap_increase =
214 OverlapIncreaseToAdd(node_rect, i, expanded_rects[i]); 215 OverlapIncreaseToAdd(node_rect, i, expanded_rects[i]);
215 if (overlap_increase < least_overlap_increase) { 216 if (overlap_increase < least_overlap_increase) {
216 least_overlap_increase = overlap_increase; 217 least_overlap_increase = overlap_increase;
217 best_node = children_[i]; 218 best_node = children_[i];
218 has_tied_node = false; 219 has_tied_node = false;
219 } else if (overlap_increase == least_overlap_increase) { 220 } else if (overlap_increase == least_overlap_increase) {
220 has_tied_node = true; 221 has_tied_node = true;
Peter Kasting 2014/05/02 18:04:57 Nit: This can go below the conditional (more effic
luken 2014/05/08 00:00:08 Done.
221 // If we are tied at zero there is no possible better overlap increase, 222 // If we are tied at zero there is no possible better overlap increase,
222 // so we can report a tie early. 223 // so we can report a tie early.
223 if (overlap_increase == 0) { 224 if (overlap_increase == 0) {
224 return NULL; 225 return NULL;
225 } 226 }
226 } 227 }
227 } 228 }
228 229
229 // If we ended up with a tie return NULL to report it. 230 // If we ended up with a tie return NULL to report it.
230 if (has_tied_node) 231 if (has_tied_node)
231 return NULL; 232 return NULL;
232 233
233 return best_node; 234 return best_node;
234 } 235 }
235 236
236 int RTree::Node::OverlapIncreaseToAdd(const Rect& rect, 237 int RTree::Node::OverlapIncreaseToAdd(const Rect& rect,
237 size_t candidate, 238 size_t candidate,
238 const Rect& expanded_rect) { 239 const Rect& expanded_rect) {
239 Node* candidate_node = children_[candidate]; 240 Node* candidate_node = children_[candidate];
Peter Kasting 2014/05/02 18:04:57 This definitely deserves a DCHECK that |candidate|
luken 2014/05/08 00:00:08 Done.
240 241
241 // Early-out option for when rect is contained completely within candidate. 242 // Early-out option for when rect is contained completely within candidate.
242 if (candidate_node->rect_.Contains(rect)) { 243 if (candidate_node->rect_.Contains(rect)) {
243 return 0; 244 return 0;
244 } 245 }
245 246
246 int total_original_overlap = 0; 247 int total_original_overlap = 0;
247 int total_expanded_overlap = 0; 248 int total_expanded_overlap = 0;
248 249
249 // Now calculate overlap with all other rects in this node. 250 // Now calculate overlap with all other rects in this node.
250 for (size_t i = 0; i < children_.size(); ++i) { 251 for (size_t i = 0; i < children_.size(); ++i) {
251 // Skip calculating overlap with the candidate rect. 252 // Skip calculating overlap with the candidate rect.
252 if (i == candidate) 253 if (i == candidate)
253 continue; 254 continue;
254 Node* overlap_node = children_[i]; 255 Node* overlap_node = children_[i];
255 Rect overlap_rect = candidate_node->rect_; 256 Rect overlap_rect = candidate_node->rect_;
256 overlap_rect.Intersect(overlap_node->rect_); 257 overlap_rect.Intersect(overlap_node->rect_);
257 total_original_overlap += overlap_rect.size().GetArea(); 258 total_original_overlap += overlap_rect.size().GetArea();
258 Rect expanded_overlap_rect = expanded_rect; 259 Rect expanded_overlap_rect = expanded_rect;
259 expanded_overlap_rect.Intersect(overlap_node->rect_); 260 expanded_overlap_rect.Intersect(overlap_node->rect_);
260 total_expanded_overlap += expanded_overlap_rect.size().GetArea(); 261 total_expanded_overlap += expanded_overlap_rect.size().GetArea();
261 } 262 }
262 263
263 // Compare this overlap increase with best one to date, update best. 264 // Compare this overlap increase with best one to date, update best.
Peter Kasting 2014/05/02 18:04:57 This comment doesn't seem to be describing the cod
luken 2014/05/08 00:00:08 Done.
264 int overlap_increase = total_expanded_overlap - total_original_overlap; 265 int overlap_increase = total_expanded_overlap - total_original_overlap;
Peter Kasting 2014/05/02 18:04:57 Nit: Just return this directly, don't create a tem
luken 2014/05/14 00:12:04 Done.
265 return overlap_increase; 266 return overlap_increase;
266 } 267 }
267 268
268 size_t RTree::Node::AddChild(Node* node) { 269 size_t RTree::Node::AddChild(Node* node) {
269 DCHECK(node); 270 DCHECK(node);
270 // Sanity-check that the level of the child being added is one more than ours. 271 // Sanity-check that the level of the child being added is one more than ours.
Peter Kasting 2014/05/02 18:04:57 It's actually one less.
luken 2014/05/08 00:00:08 Done.
271 DCHECK_EQ(level_ - 1, node->level_); 272 DCHECK_EQ(level_ - 1, node->level_);
272 node->parent_ = this; 273 node->parent_ = this;
273 children_.push_back(node); 274 children_.push_back(node);
274 rect_.Union(node->rect_); 275 rect_.Union(node->rect_);
275 return children_.size(); 276 return children_.size();
276 } 277 }
277 278
278 RTree::Node* RTree::Node::Split(size_t min_children, size_t max_children) { 279 RTree::Node* RTree::Node::Split(size_t min_children, size_t max_children) {
279 // Please don't attempt to split a record Node. 280 // Please don't attempt to split a record Node.
Peter Kasting 2014/05/02 18:04:57 Since record nodes have no children, this DCHECK i
luken 2014/05/08 00:00:08 Done.
280 DCHECK(!key_); 281 DCHECK(!key_);
281 // We should have too many children to begin with. 282 // We should have too many children to begin with.
282 DCHECK_GT(children_.size(), max_children); 283 DCHECK_GT(children_.size(), max_children);
283 // First determine if splitting along the horizontal or vertical axis. We 284 // First determine if splitting along the horizontal or vertical axis. We
Peter Kasting 2014/05/02 18:04:57 Nit: splitting -> we should split
luken 2014/05/08 00:00:08 Done.
284 // sort the rectangles of our children by lower then upper values along both 285 // sort the rectangles of our children by lower then upper values along both
285 // horizontal and vertical axes. 286 // horizontal and vertical axes.
286 std::vector<Node*> vertical_sort(children_.get()); 287 std::vector<Node*> vertical_sort(children_.get());
287 std::vector<Node*> horizontal_sort(children_.get()); 288 std::vector<Node*> horizontal_sort(children_.get());
288 std::sort(vertical_sort.begin(), 289 std::sort(vertical_sort.begin(),
289 vertical_sort.end(), 290 vertical_sort.end(),
290 &RTree::Node::CompareVertical); 291 &RTree::Node::CompareVertical);
291 std::sort(horizontal_sort.begin(), 292 std::sort(horizontal_sort.begin(),
292 horizontal_sort.end(), 293 horizontal_sort.end(),
293 &RTree::Node::CompareHorizontal); 294 &RTree::Node::CompareHorizontal);
294 295
295 // We will be examining the bounding boxes of different splits of our children 296 // We will be examining the bounding boxes of different splits of our children
296 // sorted along each axis. Here we precompute the bounding boxes of these 297 // sorted along each axis. Here we precompute the bounding boxes of these
297 // distributions. For the low bounds the ith element can be considered the 298 // distributions. For the low bounds the ith element can be considered the
298 // union of all rects [0,i] in the relevant sorted axis array. 299 // union of all rects [0,i] in the relevant sorted axis array.
Peter Kasting 2014/05/02 18:04:57 Nit: Try to avoid duplicating commentary here and
luken 2014/05/08 00:00:08 Done.
299 std::vector<Rect> low_vertical_bounds; 300 std::vector<Rect> low_vertical_bounds;
300 std::vector<Rect> low_horizontal_bounds; 301 std::vector<Rect> low_horizontal_bounds;
301 BuildLowBounds(vertical_sort, 302 BuildLowBounds(vertical_sort,
302 horizontal_sort, 303 horizontal_sort,
303 &low_vertical_bounds, 304 &low_vertical_bounds,
304 &low_horizontal_bounds); 305 &low_horizontal_bounds);
305 306
306 // For the high bounds the ith element can be considered the union of all 307 // For the high bounds the ith element can be considered the union of all
307 // rects [i, children_.size()) in the relevant sorted axis array. 308 // rects [i, children_.size()) in the relevant sorted axis array.
308 std::vector<Rect> high_vertical_bounds; 309 std::vector<Rect> high_vertical_bounds;
(...skipping 19 matching lines...) Expand all
328 low_vertical_bounds, high_vertical_bounds, vertical_sort, split_index); 329 low_vertical_bounds, high_vertical_bounds, vertical_sort, split_index);
329 } else { 330 } else {
330 size_t split_index = ChooseSplitIndex(min_children, 331 size_t split_index = ChooseSplitIndex(min_children,
331 max_children, 332 max_children,
332 low_horizontal_bounds, 333 low_horizontal_bounds,
333 high_horizontal_bounds); 334 high_horizontal_bounds);
334 sibling = DivideChildren(low_horizontal_bounds, 335 sibling = DivideChildren(low_horizontal_bounds,
335 high_horizontal_bounds, 336 high_horizontal_bounds,
336 horizontal_sort, 337 horizontal_sort,
337 split_index); 338 split_index);
338 } 339 }
Peter Kasting 2014/05/02 18:04:57 I suggest the alternate formulation below. Not on
luken 2014/05/08 00:00:08 Done.
339 340
340 return sibling; 341 return sibling;
341 } 342 }
342 343
343 // static 344 // static
344 void RTree::Node::BuildLowBounds(const std::vector<Node*>& vertical_sort, 345 void RTree::Node::BuildLowBounds(const std::vector<Node*>& vertical_sort,
345 const std::vector<Node*>& horizontal_sort, 346 const std::vector<Node*>& horizontal_sort,
346 std::vector<Rect>* vertical_bounds, 347 std::vector<Rect>* vertical_bounds,
347 std::vector<Rect>* horizontal_bounds) { 348 std::vector<Rect>* horizontal_bounds) {
348 DCHECK_EQ(vertical_sort.size(), horizontal_sort.size()); 349 DCHECK_EQ(vertical_sort.size(), horizontal_sort.size());
349 Rect vertical_bounds_rect; 350 Rect vertical_bounds_rect;
350 Rect horizontal_bounds_rect; 351 Rect horizontal_bounds_rect;
351 vertical_bounds->reserve(vertical_sort.size()); 352 vertical_bounds->reserve(vertical_sort.size());
352 horizontal_bounds->reserve(horizontal_sort.size()); 353 horizontal_bounds->reserve(horizontal_sort.size());
353 for (size_t i = 0; i < vertical_sort.size(); ++i) { 354 for (size_t i = 0; i < vertical_sort.size(); ++i) {
Peter Kasting 2014/05/02 18:04:57 Nit: I would split this into two loops (horizontal
luken 2014/05/08 00:00:08 Done.
354 vertical_bounds_rect.Union(vertical_sort[i]->rect_); 355 vertical_bounds_rect.Union(vertical_sort[i]->rect_);
355 horizontal_bounds_rect.Union(horizontal_sort[i]->rect_); 356 horizontal_bounds_rect.Union(horizontal_sort[i]->rect_);
356 vertical_bounds->push_back(vertical_bounds_rect); 357 vertical_bounds->push_back(vertical_bounds_rect);
357 horizontal_bounds->push_back(horizontal_bounds_rect); 358 horizontal_bounds->push_back(horizontal_bounds_rect);
358 } 359 }
359 } 360 }
360 361
361 // static 362 // static
362 void RTree::Node::BuildHighBounds(const std::vector<Node*>& vertical_sort, 363 void RTree::Node::BuildHighBounds(const std::vector<Node*>& vertical_sort,
363 const std::vector<Node*>& horizontal_sort, 364 const std::vector<Node*>& horizontal_sort,
364 std::vector<Rect>* vertical_bounds, 365 std::vector<Rect>* vertical_bounds,
365 std::vector<Rect>* horizontal_bounds) { 366 std::vector<Rect>* horizontal_bounds) {
366 DCHECK_EQ(vertical_sort.size(), horizontal_sort.size()); 367 DCHECK_EQ(vertical_sort.size(), horizontal_sort.size());
367 Rect vertical_bounds_rect; 368 Rect vertical_bounds_rect;
368 Rect horizontal_bounds_rect; 369 Rect horizontal_bounds_rect;
369 vertical_bounds->resize(vertical_sort.size()); 370 vertical_bounds->resize(vertical_sort.size());
370 horizontal_bounds->resize(horizontal_sort.size()); 371 horizontal_bounds->resize(horizontal_sort.size());
371 for (int i = static_cast<int>(vertical_sort.size()) - 1; i >= 0; --i) { 372 for (int i = static_cast<int>(vertical_sort.size()) - 1; i >= 0; --i) {
Peter Kasting 2014/05/02 18:04:57 Nit: I would again use two loops. For maximum saf
luken 2014/05/08 00:00:08 Done.
372 vertical_bounds_rect.Union(vertical_sort[i]->rect_); 373 vertical_bounds_rect.Union(vertical_sort[i]->rect_);
373 horizontal_bounds_rect.Union(horizontal_sort[i]->rect_); 374 horizontal_bounds_rect.Union(horizontal_sort[i]->rect_);
374 vertical_bounds->at(i) = vertical_bounds_rect; 375 vertical_bounds->at(i) = vertical_bounds_rect;
375 horizontal_bounds->at(i) = horizontal_bounds_rect; 376 horizontal_bounds->at(i) = horizontal_bounds_rect;
376 } 377 }
377 } 378 }
378 379
379 // static 380 // static
380 bool RTree::Node::ChooseSplitAxis( 381 bool RTree::Node::ChooseSplitAxis(
381 const std::vector<Rect>& low_vertical_bounds, 382 const std::vector<Rect>& low_vertical_bounds,
382 const std::vector<Rect>& high_vertical_bounds, 383 const std::vector<Rect>& high_vertical_bounds,
383 const std::vector<Rect>& low_horizontal_bounds, 384 const std::vector<Rect>& low_horizontal_bounds,
384 const std::vector<Rect>& high_horizontal_bounds, 385 const std::vector<Rect>& high_horizontal_bounds,
385 size_t min_children, 386 size_t min_children,
386 size_t max_children) { 387 size_t max_children) {
Peter Kasting 2014/05/02 18:04:57 If you wrote a helper function, int SmallestMargi
luken 2014/05/08 00:00:08 Done.
387 // Examine the possible distributions of each sorted list by iterating through 388 // Examine the possible distributions of each sorted list by iterating through
388 // valid split points p, min_children <= p <= max_children - min_children, and 389 // valid split points p, min_children <= p <= max_children - min_children, and
Peter Kasting 2014/05/02 18:04:57 This looks weird to me. I would think "max_childr
luken 2014/05/08 00:00:08 This code is now deprecated, but we really do need
Peter Kasting 2014/05/08 18:08:21 OK, so the node we're splitting is assumed to have
luken 2014/05/14 00:12:04 It's assumed to have max_children + 1 nodes, but y
389 // computing the sums of the margins of the bounding boxes in each group. 390 // computing the sums of the margins of the bounding boxes in each group.
390 // Smallest margin sum will determine split axis. 391 // Smallest margin sum will determine split axis.
391 int smallest_horizontal_margin_sum = std::numeric_limits<int>::max(); 392 int smallest_horizontal_margin_sum = std::numeric_limits<int>::max();
392 int smallest_vertical_margin_sum = std::numeric_limits<int>::max(); 393 int smallest_vertical_margin_sum = std::numeric_limits<int>::max();
393 for (size_t p = min_children; p < max_children - min_children; ++p) { 394 for (size_t p = min_children; p < max_children - min_children; ++p) {
394 int horizontal_margin_sum = 395 int horizontal_margin_sum =
395 low_horizontal_bounds[p].width() + low_horizontal_bounds[p].height() + 396 low_horizontal_bounds[p].width() + low_horizontal_bounds[p].height() +
396 high_horizontal_bounds[p].width() + high_horizontal_bounds[p].height(); 397 high_horizontal_bounds[p].width() + high_horizontal_bounds[p].height();
397 int vertical_margin_sum = 398 int vertical_margin_sum =
398 low_vertical_bounds[p].width() + low_vertical_bounds[p].height() + 399 low_vertical_bounds[p].width() + low_vertical_bounds[p].height() +
(...skipping 11 matching lines...) Expand all
410 // distributed to the two Nodes. 411 // distributed to the two Nodes.
411 bool is_vertical_split = 412 bool is_vertical_split =
412 smallest_vertical_margin_sum < smallest_horizontal_margin_sum; 413 smallest_vertical_margin_sum < smallest_horizontal_margin_sum;
413 return is_vertical_split; 414 return is_vertical_split;
414 } 415 }
415 416
416 RTree::Node* RTree::Node::DivideChildren( 417 RTree::Node* RTree::Node::DivideChildren(
417 const std::vector<Rect>& low_bounds, 418 const std::vector<Rect>& low_bounds,
418 const std::vector<Rect>& high_bounds, 419 const std::vector<Rect>& high_bounds,
419 const std::vector<Node*>& sorted_children, 420 const std::vector<Node*>& sorted_children,
420 size_t split_index) { 421 size_t split_index) {
Peter Kasting 2014/05/02 18:04:57 I suspect you want the following DCHECKs here:
luken 2014/05/08 00:00:08 Done.
421 Node* sibling = new Node(level_); 422 Node* sibling = new Node(level_);
422 sibling->parent_ = parent_; 423 sibling->parent_ = parent_;
423 rect_ = low_bounds[split_index - 1]; 424 rect_ = low_bounds[split_index - 1];
424 sibling->rect_ = high_bounds[split_index]; 425 sibling->rect_ = high_bounds[split_index];
425 // Our own children_ vector is unsorted, so we wipe it out and divide the 426 // Our own children_ vector is unsorted, so we wipe it out and divide the
Peter Kasting 2014/05/02 18:04:57 Nit: In general, if you're writing a comment about
luken 2014/05/08 00:00:08 Done.
426 // sorted bounds rects between ourselves and our sibling. 427 // sorted bounds rects between ourselves and our sibling.
427 children_.weak_clear(); 428 children_.weak_clear();
428 children_.insert(children_.end(), 429 children_.insert(children_.end(),
429 sorted_children.begin(), 430 sorted_children.begin(),
430 sorted_children.begin() + split_index); 431 sorted_children.begin() + split_index);
431 sibling->children_.insert(sibling->children_.end(), 432 sibling->children_.insert(sibling->children_.end(),
432 sorted_children.begin() + split_index, 433 sorted_children.begin() + split_index,
433 sorted_children.end()); 434 sorted_children.end());
434 435
435 // Fix up sibling parentage or it's gonna be an awkward Thanksgiving. 436 // Fix up sibling parentage or it's gonna be an awkward Thanksgiving.
Peter Kasting 2014/05/02 18:04:57 Remove this comment; the code is clear enough.
luken 2014/05/08 00:00:08 Done.
436 for (size_t i = 0; i < sibling->children_.size(); ++i) { 437 for (size_t i = 0; i < sibling->children_.size(); ++i) {
437 sibling->children_[i]->parent_ = sibling; 438 sibling->children_[i]->parent_ = sibling;
438 } 439 }
439 440
440 return sibling; 441 return sibling;
441 } 442 }
442 443
443 void RTree::Node::SetRect(const Rect& rect) { 444 void RTree::Node::SetRect(const Rect& rect) {
444 // Record nodes only, please. 445 // Record nodes only, please.
445 DCHECK(key_); 446 DCHECK(key_);
446 rect_ = rect; 447 rect_ = rect;
447 } 448 }
448 449
449 // Returns all contained record_node values for this node and all children. 450 // Returns all contained record_node values for this node and all children.
Peter Kasting 2014/05/02 18:04:57 Remove this comment, you say something similar in
luken 2014/05/08 00:00:08 Done.
450 void RTree::Node::GetAllValues(base::hash_set<intptr_t>* matches_out) const { 451 void RTree::Node::GetAllValues(base::hash_set<intptr_t>* matches_out) const {
451 if (key_) { 452 if (key_) {
452 DCHECK_EQ(level_, -1); 453 DCHECK_EQ(level_, -1);
Peter Kasting 2014/05/02 18:04:57 Again, this is not necessary.
luken 2014/05/08 00:00:08 Done.
453 matches_out->insert(key_); 454 matches_out->insert(key_);
454 } else { 455 } else {
455 for (size_t i = 0; i < children_.size(); ++i) { 456 for (size_t i = 0; i < children_.size(); ++i) {
456 Node* node = children_[i]; 457 Node* node = children_[i];
457 // Sanity-check our children. 458 // Sanity-check our children.
458 DCHECK_EQ(node->parent_, this); 459 DCHECK_EQ(node->parent_, this);
459 DCHECK_EQ(level_ - 1, node->level_); 460 DCHECK_EQ(level_ - 1, node->level_);
460 DCHECK(rect_.Contains(node->rect_)); 461 DCHECK(rect_.Contains(node->rect_));
Peter Kasting 2014/05/02 18:04:57 None of these three DCHECKs seems to have anything
luken 2014/05/08 00:00:08 Done.
461 node->GetAllValues(matches_out); 462 node->GetAllValues(matches_out);
462 } 463 }
463 } 464 }
464 } 465 }
465 466
466 // static 467 // static
467 bool RTree::Node::CompareVertical(Node* a, Node* b) { 468 bool RTree::Node::CompareVertical(Node* a, Node* b) {
468 // Sort nodes by top coordinate first. 469 // Sort nodes by top coordinate first.
Peter Kasting 2014/05/02 18:04:57 These comments pretty much duplicate the code. It
luken 2014/05/08 00:00:08 Done.
469 if (a->rect_.y() < b->rect_.y()) { 470 if (a->rect_.y() < b->rect_.y()) {
470 return true; 471 return true;
471 } else if (a->rect_.y() == b->rect_.y()) { 472 } else if (a->rect_.y() == b->rect_.y()) {
Peter Kasting 2014/05/02 18:04:57 From http://dev.chromium.org/developers/coding-sty
luken 2014/05/08 00:00:08 Done.
472 // If top coordinate is equal, sort by lowest bottom coordinate. 473 // If top coordinate is equal, sort by lowest bottom coordinate.
473 return a->rect_.height() < b->rect_.height(); 474 return a->rect_.height() < b->rect_.height();
474 } 475 }
475 return false; 476 return false;
Peter Kasting 2014/05/02 18:04:57 Nit: The second half of this function could just b
luken 2014/05/08 00:00:08 Done.
476 } 477 }
477 478
478 // static 479 // static
479 bool RTree::Node::CompareHorizontal(Node* a, Node* b) { 480 bool RTree::Node::CompareHorizontal(Node* a, Node* b) {
Peter Kasting 2014/05/02 18:04:57 Similar comments apply to this function.
luken 2014/05/08 00:00:08 Done.
480 // Sort nodes by left coordinate first. 481 // Sort nodes by left coordinate first.
481 if (a->rect_.x() < b->rect_.x()) { 482 if (a->rect_.x() < b->rect_.x()) {
482 return true; 483 return true;
483 } else if (a->rect_.x() == b->rect_.x()) { 484 } else if (a->rect_.x() == b->rect_.x()) {
484 // If left coordinate is equal, sort by lowest right coordinate. 485 // If left coordinate is equal, sort by lowest right coordinate.
485 return a->rect_.width() < b->rect_.width(); 486 return a->rect_.width() < b->rect_.width();
486 } 487 }
487 return false; 488 return false;
488 } 489 }
489 490
490 // Sort these two nodes by the distance of the center of their rects from the 491 // Sort these two nodes by the distance of the center of their rects from the
491 // center of their parent's rect. We don't bother with square roots because we 492 // center of their parent's rect. We don't bother with square roots because we
492 // are only comparing the two values for sorting purposes. 493 // are only comparing the two values for sorting purposes.
Peter Kasting 2014/05/02 18:04:57 This second sentence belongs in the code, directly
luken 2014/05/08 00:00:08 Done.
493 // static 494 // static
494 bool RTree::Node::CompareCenterDistanceFromParent(Node* a, Node* b) { 495 bool RTree::Node::CompareCenterDistanceFromParent(Node* a, Node* b) {
495 // This comparison assumes the nodes have the same parent. 496 // This comparison assumes the nodes have the same parent.
Peter Kasting 2014/05/02 18:04:57 All four of the comments here simply duplicate the
luken 2014/05/08 00:00:08 Done.
496 DCHECK(a->parent_ == b->parent_); 497 DCHECK(a->parent_ == b->parent_);
Peter Kasting 2014/05/02 18:04:57 Nit: DCHECK_EQ
luken 2014/05/08 00:00:08 Done.
497 // This comparison requires that each node have a parent. 498 // This comparison requires that each node have a parent.
498 DCHECK(a->parent_); 499 DCHECK(a->parent_);
Peter Kasting 2014/05/02 18:04:57 Tiny nit: I suggest putting this DCHECK first (so
luken 2014/05/08 00:00:08 Done.
499 // Sanity-check level_ of these nodes is equal. 500 // Sanity-check level_ of these nodes is equal.
500 DCHECK_EQ(a->level_, b->level_); 501 DCHECK_EQ(a->level_, b->level_);
Peter Kasting 2014/05/02 18:04:57 This function doesn't require either of these next
luken 2014/05/08 00:00:08 Done.
501 // Also the parent of the nodes should have level one higher. 502 // Also the parent of the nodes should have level one higher.
502 DCHECK_EQ(a->level_, a->parent_->level_ - 1); 503 DCHECK_EQ(a->level_, a->parent_->level_ - 1);
503 504
504 // Find the parent. 505 // Find the parent.
Peter Kasting 2014/05/02 18:04:57 Comment duplicates the code, remove it.
luken 2014/05/08 00:00:08 Done.
505 Node* p = a->parent(); 506 Node* p = a->parent();
506 507
507 Vector2d p_center = CenterOfRect(p->rect_); 508 Vector2d p_center = CenterOfRect(p->rect_);
508 Vector2d a_center = CenterOfRect(a->rect_); 509 Vector2d a_center = CenterOfRect(a->rect_);
509 Vector2d b_center = CenterOfRect(b->rect_); 510 Vector2d b_center = CenterOfRect(b->rect_);
510 511
511 return (a_center - p_center).LengthSquared() < 512 return (a_center - p_center).LengthSquared() <
512 (b_center - p_center).LengthSquared(); 513 (b_center - p_center).LengthSquared();
513 } 514 }
514 515
515 size_t RTree::Node::ChooseSplitIndex(size_t min_children, 516 size_t RTree::Node::ChooseSplitIndex(size_t min_children,
516 size_t max_children, 517 size_t max_children,
517 const std::vector<Rect>& low_bounds, 518 const std::vector<Rect>& low_bounds,
518 const std::vector<Rect>& high_bounds) { 519 const std::vector<Rect>& high_bounds) {
Peter Kasting 2014/05/02 18:04:57 Again, this function probably deserves DCHECKs lik
luken 2014/05/08 00:00:08 DCHECKs added. Index is correct. I'll add a comme
519 int smallest_overlap_area = std::numeric_limits<int>::max(); 520 int smallest_overlap_area = std::numeric_limits<int>::max();
Peter Kasting 2014/05/02 18:04:57 This whole block can be simplified: int smalles
luken 2014/05/08 00:00:08 Done, although my version only computed combined_a
520 int smallest_combined_area = std::numeric_limits<int>::max(); 521 int smallest_combined_area = std::numeric_limits<int>::max();
521 size_t optimal_split_index = 0; 522 size_t optimal_split_index = 0;
522 for (size_t p = min_children; p < max_children - min_children; ++p) { 523 for (size_t p = min_children; p < max_children - min_children; ++p) {
523 Rect overlap_bounds = low_bounds[p]; 524 Rect overlap_bounds = low_bounds[p];
524 overlap_bounds.Union(high_bounds[p]); 525 overlap_bounds.Union(high_bounds[p]);
525 int overlap_area = overlap_bounds.size().GetArea(); 526 int overlap_area = overlap_bounds.size().GetArea();
526 if (overlap_area < smallest_overlap_area) { 527 if (overlap_area < smallest_overlap_area) {
527 smallest_overlap_area = overlap_area; 528 smallest_overlap_area = overlap_area;
528 smallest_combined_area = 529 smallest_combined_area =
529 low_bounds[p].size().GetArea() + high_bounds[p].size().GetArea(); 530 low_bounds[p].size().GetArea() + high_bounds[p].size().GetArea();
530 optimal_split_index = p; 531 optimal_split_index = p;
531 } else if (overlap_area == smallest_overlap_area) { 532 } else if (overlap_area == smallest_overlap_area) {
532 // Break ties with smallest combined area of the two bounding boxes. 533 // Break ties with smallest combined area of the two bounding boxes.
533 int combined_area = 534 int combined_area =
534 low_bounds[p].size().GetArea() + high_bounds[p].size().GetArea(); 535 low_bounds[p].size().GetArea() + high_bounds[p].size().GetArea();
535 if (combined_area < smallest_combined_area) { 536 if (combined_area < smallest_combined_area) {
536 smallest_combined_area = combined_area; 537 smallest_combined_area = combined_area;
537 optimal_split_index = p; 538 optimal_split_index = p;
538 } 539 }
539 } 540 }
540 } 541 }
541 542
542 // optimal_split_index currently points at the last element in the first set, 543 // optimal_split_index currently points at the last element in the first set,
543 // so advance it by 1 to point at the first element in the second set. 544 // so advance it by 1 to point at the first element in the second set.
544 return optimal_split_index + 1; 545 return optimal_split_index + 1;
545 } 546 }
546 547
547 void RTree::Node::RecomputeBoundsNoParents() { 548 void RTree::Node::RecomputeBoundsNoParents() {
548 // Clear our rectangle, then reset it to union of our children. 549 // Clear our rectangle, then reset it to union of our children.
Peter Kasting 2014/05/02 18:04:57 This comment isn't necessary.
luken 2014/05/08 00:00:08 Done.
549 rect_.SetRect(0, 0, 0, 0); 550 rect_.SetRect(0, 0, 0, 0);
550 for (size_t i = 0; i < children_.size(); ++i) { 551 for (size_t i = 0; i < children_.size(); ++i) {
551 rect_.Union(children_[i]->rect_); 552 rect_.Union(children_[i]->rect_);
552 } 553 }
553 } 554 }
554 555
555 RTree::RTree(size_t min_children, size_t max_children) 556 RTree::RTree(size_t min_children, size_t max_children)
556 : root_(new Node(0)), 557 : root_(new Node(0)),
557 min_children_(min_children), 558 min_children_(min_children),
558 max_children_(max_children) { 559 max_children_(max_children) {
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 int starting_level = -1; 737 int starting_level = -1;
737 InsertNode(orphans[i], &starting_level); 738 InsertNode(orphans[i], &starting_level);
738 } 739 }
739 740
740 // Clear out the orphans list without deleting any of the children, as they 741 // Clear out the orphans list without deleting any of the children, as they
741 // have been re-inserted into the tree. 742 // have been re-inserted into the tree.
742 orphans.weak_clear(); 743 orphans.weak_clear();
743 } 744 }
744 745
745 } // namespace gfx 746 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698