cell_index.go (16660B)
1 // Copyright 2020 Google Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package s2 16 17 import ( 18 "sort" 19 ) 20 21 const ( 22 // A special label indicating that the ContentsIterator done is true. 23 cellIndexDoneContents = -1 24 ) 25 26 // cellIndexNode represents a node in the CellIndex. Cells are organized in a 27 // tree such that the ancestors of a given node contain that node. 28 type cellIndexNode struct { 29 cellID CellID 30 label int32 31 parent int32 32 } 33 34 // newCellIndexNode returns a node with the appropriate default values. 35 func newCellIndexNode() cellIndexNode { 36 return cellIndexNode{ 37 cellID: 0, 38 label: cellIndexDoneContents, 39 parent: -1, 40 } 41 } 42 43 // A rangeNode represents a range of leaf CellIDs. The range starts at 44 // startID (a leaf cell) and ends at the startID field of the next 45 // rangeNode. contents points to the node of the CellIndex cellTree 46 // representing the cells that overlap this range. 47 type rangeNode struct { 48 startID CellID // First leaf cell contained by this range. 49 contents int32 // Contents of this node (an index within the cell tree). 50 } 51 52 // CellIndexIterator is an iterator that visits the entire set of indexed 53 // (CellID, label) pairs in an unspecified order. 54 type CellIndexIterator struct { 55 // TODO(roberts): Implement 56 } 57 58 // NewCellIndexIterator creates an iterator for the given CellIndex. 59 func NewCellIndexIterator(index *CellIndex) *CellIndexIterator { 60 return &CellIndexIterator{} 61 } 62 63 // CellIndexRangeIterator is an iterator that seeks and iterates over a set of 64 // non-overlapping leaf cell ranges that cover the entire sphere. The indexed 65 // (CellID, label) pairs that intersect the current leaf cell range can be 66 // visited using CellIndexContentsIterator (see below). 67 type CellIndexRangeIterator struct { 68 rangeNodes []rangeNode 69 pos int 70 nonEmpty bool 71 } 72 73 // NewCellIndexRangeIterator creates an iterator for the given CellIndex. 74 // The iterator is initially *unpositioned*; you must call a positioning method 75 // such as Begin() or Seek() before accessing its contents. 76 func NewCellIndexRangeIterator(index *CellIndex) *CellIndexRangeIterator { 77 return &CellIndexRangeIterator{ 78 rangeNodes: index.rangeNodes, 79 } 80 } 81 82 // NewCellIndexNonEmptyRangeIterator creates an iterator for the given CellIndex. 83 // The iterator is initially *unpositioned*; you must call a positioning method such as 84 // Begin() or Seek() before accessing its contents. 85 func NewCellIndexNonEmptyRangeIterator(index *CellIndex) *CellIndexRangeIterator { 86 return &CellIndexRangeIterator{ 87 rangeNodes: index.rangeNodes, 88 nonEmpty: true, 89 } 90 } 91 92 // StartID reports the CellID of the start of the current range of leaf CellIDs. 93 // 94 // If done is true, this returns the last possible CellID. This property means 95 // that most loops do not need to test done explicitly. 96 func (c *CellIndexRangeIterator) StartID() CellID { 97 return c.rangeNodes[c.pos].startID 98 } 99 100 // LimitID reports the non-inclusive end of the current range of leaf CellIDs. 101 // 102 // This assumes the iterator is not done. 103 func (c *CellIndexRangeIterator) LimitID() CellID { 104 return c.rangeNodes[c.pos+1].startID 105 } 106 107 // IsEmpty reports if no (CellID, label) pairs intersect this range. 108 // Also returns true if done() is true. 109 func (c *CellIndexRangeIterator) IsEmpty() bool { 110 return c.rangeNodes[c.pos].contents == cellIndexDoneContents 111 } 112 113 // Begin positions the iterator at the first range of leaf cells (if any). 114 func (c *CellIndexRangeIterator) Begin() { 115 c.pos = 0 116 for c.nonEmpty && c.IsEmpty() && !c.Done() { 117 c.pos++ 118 } 119 } 120 121 // Prev positions the iterator at the previous entry and reports whether it was not 122 // already positioned at the beginning. 123 func (c *CellIndexRangeIterator) Prev() bool { 124 if c.nonEmpty { 125 return c.nonEmptyPrev() 126 } 127 return c.prev() 128 } 129 130 // prev is used to position the iterator at the previous entry without checking 131 // if nonEmpty is true to prevent unwanted recursion. 132 func (c *CellIndexRangeIterator) prev() bool { 133 if c.pos == 0 { 134 return false 135 } 136 137 c.pos-- 138 return true 139 } 140 141 // Prev positions the iterator at the previous entry, and reports whether it was 142 // already positioned at the beginning. 143 func (c *CellIndexRangeIterator) nonEmptyPrev() bool { 144 for c.prev() { 145 if !c.IsEmpty() { 146 return true 147 } 148 } 149 150 // Return the iterator to its original position. 151 if c.IsEmpty() && !c.Done() { 152 c.Next() 153 } 154 return false 155 } 156 157 // Next advances the iterator to the next range of leaf cells. 158 // 159 // This assumes the iterator is not done. 160 func (c *CellIndexRangeIterator) Next() { 161 c.pos++ 162 for c.nonEmpty && c.IsEmpty() && !c.Done() { 163 c.pos++ 164 } 165 } 166 167 // Advance reports if advancing would leave it positioned on a valid range. If 168 // the value would not be valid, the positioning is not changed. 169 func (c *CellIndexRangeIterator) Advance(n int) bool { 170 // Note that the last element of rangeNodes is a sentinel value. 171 if n >= len(c.rangeNodes)-1-c.pos { 172 return false 173 } 174 c.pos += n 175 return true 176 } 177 178 // Finish positions the iterator so that done is true. 179 func (c *CellIndexRangeIterator) Finish() { 180 // Note that the last element of rangeNodes is a sentinel value. 181 c.pos = len(c.rangeNodes) - 1 182 } 183 184 // Done reports if the iterator is positioned beyond the last valid range. 185 func (c *CellIndexRangeIterator) Done() bool { 186 return c.pos >= len(c.rangeNodes)-1 187 } 188 189 // Seek positions the iterator at the first range with startID >= target. 190 // Such an entry always exists as long as "target" is a valid leaf cell. 191 // 192 // Note that it is valid to access startID even when done is true. 193 func (c *CellIndexRangeIterator) Seek(target CellID) { 194 c.pos = sort.Search(len(c.rangeNodes), func(i int) bool { 195 return c.rangeNodes[i].startID > target 196 }) - 1 197 198 // Ensure we don't go beyond the beginning. 199 if c.pos < 0 { 200 c.pos = 0 201 } 202 203 // Nonempty needs to find the next non-empty entry. 204 for c.nonEmpty && c.IsEmpty() && !c.Done() { 205 // c.Next() 206 c.pos++ 207 } 208 } 209 210 // CellIndexContentsIterator is an iterator that visits the (CellID, label) pairs 211 // that cover a set of leaf cell ranges (see CellIndexRangeIterator). Note that 212 // when multiple leaf cell ranges are visited, this iterator only guarantees that 213 // each result will be reported at least once, i.e. duplicate values may be 214 // suppressed. If you want duplicate values to be reported again, be sure to call 215 // Clear first. 216 // 217 // In particular, the implementation guarantees that when multiple leaf 218 // cell ranges are visited in monotonically increasing order, then each 219 // (CellID, label) pair is reported exactly once. 220 type CellIndexContentsIterator struct { 221 // The maximum index within the cellTree slice visited during the 222 // previous call to StartUnion. This is used to eliminate duplicate 223 // values when StartUnion is called multiple times. 224 nodeCutoff int32 225 226 // The maximum index within the cellTree visited during the 227 // current call to StartUnion. This is used to update nodeCutoff. 228 nextNodeCutoff int32 229 230 // The value of startID from the previous call to StartUnion. 231 // This is used to check whether these values are monotonically 232 // increasing. 233 prevStartID CellID 234 235 // The cell tree from CellIndex 236 cellTree []cellIndexNode 237 238 // A copy of the current node in the cell tree. 239 node cellIndexNode 240 } 241 242 // NewCellIndexContentsIterator returns a new contents iterator. 243 // 244 // Note that the iterator needs to be positioned using StartUnion before 245 // it can be safely used. 246 func NewCellIndexContentsIterator(index *CellIndex) *CellIndexContentsIterator { 247 it := &CellIndexContentsIterator{ 248 cellTree: index.cellTree, 249 prevStartID: 0, 250 nodeCutoff: -1, 251 nextNodeCutoff: -1, 252 node: cellIndexNode{label: cellIndexDoneContents}, 253 } 254 return it 255 } 256 257 // Clear clears all state with respect to which range(s) have been visited. 258 func (c *CellIndexContentsIterator) Clear() { 259 c.prevStartID = 0 260 c.nodeCutoff = -1 261 c.nextNodeCutoff = -1 262 c.node.label = cellIndexDoneContents 263 } 264 265 // CellID returns the current CellID. 266 func (c *CellIndexContentsIterator) CellID() CellID { 267 return c.node.cellID 268 } 269 270 // Label returns the current Label. 271 func (c *CellIndexContentsIterator) Label() int32 { 272 return c.node.label 273 } 274 275 // Next advances the iterator to the next (CellID, label) pair covered by the 276 // current leaf cell range. 277 // 278 // This requires the iterator to not be done. 279 func (c *CellIndexContentsIterator) Next() { 280 if c.node.parent <= c.nodeCutoff { 281 // We have already processed this node and its ancestors. 282 c.nodeCutoff = c.nextNodeCutoff 283 c.node.label = cellIndexDoneContents 284 } else { 285 c.node = c.cellTree[c.node.parent] 286 } 287 } 288 289 // Done reports if all (CellID, label) pairs have been visited. 290 func (c *CellIndexContentsIterator) Done() bool { 291 return c.node.label == cellIndexDoneContents 292 } 293 294 // StartUnion positions the ContentsIterator at the first (cell_id, label) pair 295 // that covers the given leaf cell range. Note that when multiple leaf cell 296 // ranges are visited using the same ContentsIterator, duplicate values 297 // may be suppressed. If you don't want this behavior, call Reset() first. 298 func (c *CellIndexContentsIterator) StartUnion(r *CellIndexRangeIterator) { 299 if r.StartID() < c.prevStartID { 300 c.nodeCutoff = -1 // Can't automatically eliminate duplicates. 301 } 302 c.prevStartID = r.StartID() 303 304 contents := r.rangeNodes[r.pos].contents 305 if contents <= c.nodeCutoff { 306 c.node.label = cellIndexDoneContents 307 } else { 308 c.node = c.cellTree[contents] 309 } 310 311 // When visiting ancestors, we can stop as soon as the node index is smaller 312 // than any previously visited node index. Because indexes are assigned 313 // using a preorder traversal, such nodes are guaranteed to have already 314 // been reported. 315 c.nextNodeCutoff = contents 316 } 317 318 // CellIndex stores a collection of (CellID, label) pairs. 319 // 320 // The CellIDs may be overlapping or contain duplicate values. For example, a 321 // CellIndex could store a collection of CellUnions, where each CellUnion 322 // gets its own non-negative int32 label. 323 // 324 // Similar to ShapeIndex and PointIndex which map each stored element to an 325 // identifier, CellIndex stores a label that is typically used to map the 326 // results of queries back to client's specific data. 327 // 328 // The zero value for a CellIndex is sufficient when constructing a CellIndex. 329 // 330 // To build a CellIndex where each Cell has a distinct label, call Add for each 331 // (CellID, label) pair, and then Build the index. For example: 332 // 333 // // contents is a mapping of an identifier in my system (restaurantID, 334 // // vehicleID, etc) to a CellID 335 // var contents = map[int32]CellID{...} 336 // 337 // for key, val := range contents { 338 // index.Add(val, key) 339 // } 340 // 341 // index.Build() 342 // 343 // There is also a helper method that adds all elements of CellUnion with the 344 // same label: 345 // 346 // index.AddCellUnion(cellUnion, label) 347 // 348 // Note that the index is not dynamic; the contents of the index cannot be 349 // changed once it has been built. Adding more after calling Build results in 350 // undefined behavior of the index. 351 // 352 // There are several options for retrieving data from the index. The simplest 353 // is to use a built-in method such as IntersectingLabels (which returns 354 // the labels of all cells that intersect a given target CellUnion): 355 // 356 // labels := index.IntersectingLabels(targetUnion); 357 // 358 // Alternatively, you can use a ClosestCellQuery which computes the cell(s) 359 // that are closest to a given target geometry. 360 // 361 // For example, here is how to find all cells that are closer than 362 // distanceLimit to a given target point: 363 // 364 // query := NewClosestCellQuery(cellIndex, opts) 365 // target := NewMinDistanceToPointTarget(targetPoint); 366 // for result := range query.FindCells(target) { 367 // // result.Distance() is the distance to the target. 368 // // result.CellID() is the indexed CellID. 369 // // result.Label() is the label associated with the CellID. 370 // DoSomething(targetPoint, result); 371 // } 372 // 373 // Internally, the index consists of a set of non-overlapping leaf cell ranges 374 // that subdivide the sphere and such that each range intersects a particular 375 // set of (cellID, label) pairs. 376 // 377 // Most clients should use either the methods such as VisitIntersectingCells 378 // and IntersectingLabels, or a helper such as ClosestCellQuery. 379 type CellIndex struct { 380 // A tree of (cellID, label) pairs such that if X is an ancestor of Y, then 381 // X.cellID contains Y.cellID. The contents of a given range of leaf 382 // cells can be represented by pointing to a node of this tree. 383 cellTree []cellIndexNode 384 385 // The last element of rangeNodes is a sentinel value, which is necessary 386 // in order to represent the range covered by the previous element. 387 rangeNodes []rangeNode 388 } 389 390 // Add adds the given CellID and Label to the index. 391 func (c *CellIndex) Add(id CellID, label int32) { 392 if label < 0 { 393 panic("labels must be non-negative") 394 } 395 c.cellTree = append(c.cellTree, cellIndexNode{cellID: id, label: label, parent: -1}) 396 } 397 398 // AddCellUnion adds all of the elements of the given CellUnion to the index with the same label. 399 func (c *CellIndex) AddCellUnion(cu CellUnion, label int32) { 400 if label < 0 { 401 panic("labels must be non-negative") 402 } 403 for _, cell := range cu { 404 c.Add(cell, label) 405 } 406 } 407 408 // Build builds the index for use. This method should only be called once. 409 func (c *CellIndex) Build() { 410 // To build the cell tree and leaf cell ranges, we maintain a stack of 411 // (CellID, label) pairs that contain the current leaf cell. This struct 412 // represents an instruction to push or pop a (cellID, label) pair. 413 // 414 // If label >= 0, the (cellID, label) pair is pushed on the stack. 415 // If CellID == SentinelCellID, a pair is popped from the stack. 416 // Otherwise the stack is unchanged but a rangeNode is still emitted. 417 418 // delta represents an entry in a stack of (CellID, label) pairs used in the 419 // construction of the CellIndex structure. 420 type delta struct { 421 startID CellID 422 cellID CellID 423 label int32 424 } 425 426 deltas := make([]delta, 0, 2*len(c.cellTree)+2) 427 428 // Create two deltas for each (cellID, label) pair: one to add the pair to 429 // the stack (at the start of its leaf cell range), and one to remove it from 430 // the stack (at the end of its leaf cell range). 431 for _, node := range c.cellTree { 432 deltas = append(deltas, delta{ 433 startID: node.cellID.RangeMin(), 434 cellID: node.cellID, 435 label: node.label, 436 }) 437 deltas = append(deltas, delta{ 438 startID: node.cellID.RangeMax().Next(), 439 cellID: SentinelCellID, 440 label: -1, 441 }) 442 } 443 444 // We also create two special deltas to ensure that a RangeNode is emitted at 445 // the beginning and end of the CellID range. 446 deltas = append(deltas, delta{ 447 startID: CellIDFromFace(0).ChildBeginAtLevel(maxLevel), 448 cellID: CellID(0), 449 label: -1, 450 }) 451 deltas = append(deltas, delta{ 452 startID: CellIDFromFace(5).ChildEndAtLevel(maxLevel), 453 cellID: CellID(0), 454 label: -1, 455 }) 456 457 sort.Slice(deltas, func(i, j int) bool { 458 // deltas are sorted first by startID, then in reverse order by cellID, 459 // and then by label. This is necessary to ensure that (1) larger cells 460 // are pushed on the stack before smaller cells, and (2) cells are popped 461 // off the stack before any new cells are added. 462 463 if si, sj := deltas[i].startID, deltas[j].startID; si != sj { 464 return si < sj 465 } 466 if si, sj := deltas[i].cellID, deltas[j].cellID; si != sj { 467 return si > sj 468 } 469 return deltas[i].label < deltas[j].label 470 }) 471 472 // Now walk through the deltas to build the leaf cell ranges and cell tree 473 // (which is essentially a permanent form of the "stack" described above). 474 c.cellTree = nil 475 c.rangeNodes = nil 476 contents := int32(-1) 477 for i := 0; i < len(deltas); { 478 startID := deltas[i].startID 479 // Process all the deltas associated with the current startID. 480 for ; i < len(deltas) && deltas[i].startID == startID; i++ { 481 if deltas[i].label >= 0 { 482 c.cellTree = append(c.cellTree, cellIndexNode{ 483 cellID: deltas[i].cellID, 484 label: deltas[i].label, 485 parent: contents}) 486 contents = int32(len(c.cellTree) - 1) 487 } else if deltas[i].cellID == SentinelCellID { 488 contents = c.cellTree[contents].parent 489 } 490 } 491 c.rangeNodes = append(c.rangeNodes, rangeNode{startID, contents}) 492 } 493 } 494 495 // TODO(roberts): Differences from C++ 496 // IntersectingLabels 497 // VisitIntersectingCells 498 // CellIndexIterator