regioncoverer.go (22232B)
1 // Copyright 2015 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 "container/heap" 19 "sort" 20 ) 21 22 // RegionCoverer allows arbitrary regions to be approximated as unions of cells (CellUnion). 23 // This is useful for implementing various sorts of search and precomputation operations. 24 // 25 // Typical usage: 26 // 27 // rc := &s2.RegionCoverer{MaxLevel: 30, MaxCells: 5} 28 // r := s2.Region(CapFromCenterArea(center, area)) 29 // covering := rc.Covering(r) 30 // 31 // This yields a CellUnion of at most 5 cells that is guaranteed to cover the 32 // given region (a disc-shaped region on the sphere). 33 // 34 // For covering, only cells where (level - MinLevel) is a multiple of LevelMod will be used. 35 // This effectively allows the branching factor of the S2 CellID hierarchy to be increased. 36 // Currently the only parameter values allowed are 1, 2, or 3, corresponding to 37 // branching factors of 4, 16, and 64 respectively. 38 // 39 // Note the following: 40 // 41 // - MinLevel takes priority over MaxCells, i.e. cells below the given level will 42 // never be used even if this causes a large number of cells to be returned. 43 // 44 // - For any setting of MaxCells, up to 6 cells may be returned if that 45 // is the minimum number of cells required (e.g. if the region intersects 46 // all six face cells). Up to 3 cells may be returned even for very tiny 47 // convex regions if they happen to be located at the intersection of 48 // three cube faces. 49 // 50 // - For any setting of MaxCells, an arbitrary number of cells may be 51 // returned if MinLevel is too high for the region being approximated. 52 // 53 // - If MaxCells is less than 4, the area of the covering may be 54 // arbitrarily large compared to the area of the original region even if 55 // the region is convex (e.g. a Cap or Rect). 56 // 57 // The approximation algorithm is not optimal but does a pretty good job in 58 // practice. The output does not always use the maximum number of cells 59 // allowed, both because this would not always yield a better approximation, 60 // and because MaxCells is a limit on how much work is done exploring the 61 // possible covering as well as a limit on the final output size. 62 // 63 // Because it is an approximation algorithm, one should not rely on the 64 // stability of the output. In particular, the output of the covering algorithm 65 // may change across different versions of the library. 66 // 67 // One can also generate interior coverings, which are sets of cells which 68 // are entirely contained within a region. Interior coverings can be 69 // empty, even for non-empty regions, if there are no cells that satisfy 70 // the provided constraints and are contained by the region. Note that for 71 // performance reasons, it is wise to specify a MaxLevel when computing 72 // interior coverings - otherwise for regions with small or zero area, the 73 // algorithm may spend a lot of time subdividing cells all the way to leaf 74 // level to try to find contained cells. 75 type RegionCoverer struct { 76 MinLevel int // the minimum cell level to be used. 77 MaxLevel int // the maximum cell level to be used. 78 LevelMod int // the LevelMod to be used. 79 MaxCells int // the maximum desired number of cells in the approximation. 80 } 81 82 // NewRegionCoverer returns a region coverer with the appropriate defaults. 83 func NewRegionCoverer() *RegionCoverer { 84 return &RegionCoverer{ 85 MinLevel: 0, 86 MaxLevel: maxLevel, 87 LevelMod: 1, 88 MaxCells: 8, 89 } 90 } 91 92 type coverer struct { 93 minLevel int // the minimum cell level to be used. 94 maxLevel int // the maximum cell level to be used. 95 levelMod int // the LevelMod to be used. 96 maxCells int // the maximum desired number of cells in the approximation. 97 region Region 98 result CellUnion 99 pq priorityQueue 100 interiorCovering bool 101 } 102 103 type candidate struct { 104 cell Cell 105 terminal bool // Cell should not be expanded further. 106 numChildren int // Number of children that intersect the region. 107 children []*candidate // Actual size may be 0, 4, 16, or 64 elements. 108 priority int // Priority of the candidate. 109 } 110 111 type priorityQueue []*candidate 112 113 func (pq priorityQueue) Len() int { 114 return len(pq) 115 } 116 117 func (pq priorityQueue) Less(i, j int) bool { 118 // We want Pop to give us the highest, not lowest, priority so we use greater than here. 119 return pq[i].priority > pq[j].priority 120 } 121 122 func (pq priorityQueue) Swap(i, j int) { 123 pq[i], pq[j] = pq[j], pq[i] 124 } 125 126 func (pq *priorityQueue) Push(x interface{}) { 127 item := x.(*candidate) 128 *pq = append(*pq, item) 129 } 130 131 func (pq *priorityQueue) Pop() interface{} { 132 item := (*pq)[len(*pq)-1] 133 *pq = (*pq)[:len(*pq)-1] 134 return item 135 } 136 137 func (pq *priorityQueue) Reset() { 138 *pq = (*pq)[:0] 139 } 140 141 // newCandidate returns a new candidate with no children if the cell intersects the given region. 142 // The candidate is marked as terminal if it should not be expanded further. 143 func (c *coverer) newCandidate(cell Cell) *candidate { 144 if !c.region.IntersectsCell(cell) { 145 return nil 146 } 147 cand := &candidate{cell: cell} 148 level := int(cell.level) 149 if level >= c.minLevel { 150 if c.interiorCovering { 151 if c.region.ContainsCell(cell) { 152 cand.terminal = true 153 } else if level+c.levelMod > c.maxLevel { 154 return nil 155 } 156 } else if level+c.levelMod > c.maxLevel || c.region.ContainsCell(cell) { 157 cand.terminal = true 158 } 159 } 160 return cand 161 } 162 163 // expandChildren populates the children of the candidate by expanding the given number of 164 // levels from the given cell. Returns the number of children that were marked "terminal". 165 func (c *coverer) expandChildren(cand *candidate, cell Cell, numLevels int) int { 166 numLevels-- 167 var numTerminals int 168 last := cell.id.ChildEnd() 169 for ci := cell.id.ChildBegin(); ci != last; ci = ci.Next() { 170 childCell := CellFromCellID(ci) 171 if numLevels > 0 { 172 if c.region.IntersectsCell(childCell) { 173 numTerminals += c.expandChildren(cand, childCell, numLevels) 174 } 175 continue 176 } 177 if child := c.newCandidate(childCell); child != nil { 178 cand.children = append(cand.children, child) 179 cand.numChildren++ 180 if child.terminal { 181 numTerminals++ 182 } 183 } 184 } 185 return numTerminals 186 } 187 188 // addCandidate adds the given candidate to the result if it is marked as "terminal", 189 // otherwise expands its children and inserts it into the priority queue. 190 // Passing an argument of nil does nothing. 191 func (c *coverer) addCandidate(cand *candidate) { 192 if cand == nil { 193 return 194 } 195 196 if cand.terminal { 197 c.result = append(c.result, cand.cell.id) 198 return 199 } 200 201 // Expand one level at a time until we hit minLevel to ensure that we don't skip over it. 202 numLevels := c.levelMod 203 level := int(cand.cell.level) 204 if level < c.minLevel { 205 numLevels = 1 206 } 207 208 numTerminals := c.expandChildren(cand, cand.cell, numLevels) 209 maxChildrenShift := uint(2 * c.levelMod) 210 if cand.numChildren == 0 { 211 return 212 } else if !c.interiorCovering && numTerminals == 1<<maxChildrenShift && level >= c.minLevel { 213 // Optimization: add the parent cell rather than all of its children. 214 // We can't do this for interior coverings, since the children just 215 // intersect the region, but may not be contained by it - we need to 216 // subdivide them further. 217 cand.terminal = true 218 c.addCandidate(cand) 219 } else { 220 // We negate the priority so that smaller absolute priorities are returned 221 // first. The heuristic is designed to refine the largest cells first, 222 // since those are where we have the largest potential gain. Among cells 223 // of the same size, we prefer the cells with the fewest children. 224 // Finally, among cells with equal numbers of children we prefer those 225 // with the smallest number of children that cannot be refined further. 226 cand.priority = -(((level<<maxChildrenShift)+cand.numChildren)<<maxChildrenShift + numTerminals) 227 heap.Push(&c.pq, cand) 228 } 229 } 230 231 // adjustLevel returns the reduced "level" so that it satisfies levelMod. Levels smaller than minLevel 232 // are not affected (since cells at these levels are eventually expanded). 233 func (c *coverer) adjustLevel(level int) int { 234 if c.levelMod > 1 && level > c.minLevel { 235 level -= (level - c.minLevel) % c.levelMod 236 } 237 return level 238 } 239 240 // adjustCellLevels ensures that all cells with level > minLevel also satisfy levelMod, 241 // by replacing them with an ancestor if necessary. Cell levels smaller 242 // than minLevel are not modified (see AdjustLevel). The output is 243 // then normalized to ensure that no redundant cells are present. 244 func (c *coverer) adjustCellLevels(cells *CellUnion) { 245 if c.levelMod == 1 { 246 return 247 } 248 249 var out int 250 for _, ci := range *cells { 251 level := ci.Level() 252 newLevel := c.adjustLevel(level) 253 if newLevel != level { 254 ci = ci.Parent(newLevel) 255 } 256 if out > 0 && (*cells)[out-1].Contains(ci) { 257 continue 258 } 259 for out > 0 && ci.Contains((*cells)[out-1]) { 260 out-- 261 } 262 (*cells)[out] = ci 263 out++ 264 } 265 *cells = (*cells)[:out] 266 } 267 268 // initialCandidates computes a set of initial candidates that cover the given region. 269 func (c *coverer) initialCandidates() { 270 // Optimization: start with a small (usually 4 cell) covering of the region's bounding cap. 271 temp := &RegionCoverer{MaxLevel: c.maxLevel, LevelMod: 1, MaxCells: minInt(4, c.maxCells)} 272 273 cells := temp.FastCovering(c.region) 274 c.adjustCellLevels(&cells) 275 for _, ci := range cells { 276 c.addCandidate(c.newCandidate(CellFromCellID(ci))) 277 } 278 } 279 280 // coveringInternal generates a covering and stores it in result. 281 // Strategy: Start with the 6 faces of the cube. Discard any 282 // that do not intersect the shape. Then repeatedly choose the 283 // largest cell that intersects the shape and subdivide it. 284 // 285 // result contains the cells that will be part of the output, while pq 286 // contains cells that we may still subdivide further. Cells that are 287 // entirely contained within the region are immediately added to the output, 288 // while cells that do not intersect the region are immediately discarded. 289 // Therefore pq only contains cells that partially intersect the region. 290 // Candidates are prioritized first according to cell size (larger cells 291 // first), then by the number of intersecting children they have (fewest 292 // children first), and then by the number of fully contained children 293 // (fewest children first). 294 func (c *coverer) coveringInternal(region Region) { 295 c.region = region 296 297 c.initialCandidates() 298 for c.pq.Len() > 0 && (!c.interiorCovering || len(c.result) < c.maxCells) { 299 cand := heap.Pop(&c.pq).(*candidate) 300 301 // For interior covering we keep subdividing no matter how many children 302 // candidate has. If we reach MaxCells before expanding all children, 303 // we will just use some of them. 304 // For exterior covering we cannot do this, because result has to cover the 305 // whole region, so all children have to be used. 306 // candidate.numChildren == 1 case takes care of the situation when we 307 // already have more than MaxCells in result (minLevel is too high). 308 // Subdividing of the candidate with one child does no harm in this case. 309 if c.interiorCovering || int(cand.cell.level) < c.minLevel || cand.numChildren == 1 || len(c.result)+c.pq.Len()+cand.numChildren <= c.maxCells { 310 for _, child := range cand.children { 311 if !c.interiorCovering || len(c.result) < c.maxCells { 312 c.addCandidate(child) 313 } 314 } 315 } else { 316 cand.terminal = true 317 c.addCandidate(cand) 318 } 319 } 320 321 c.pq.Reset() 322 c.region = nil 323 324 // Rather than just returning the raw list of cell ids, we construct a cell 325 // union and then denormalize it. This has the effect of replacing four 326 // child cells with their parent whenever this does not violate the covering 327 // parameters specified (min_level, level_mod, etc). This significantly 328 // reduces the number of cells returned in many cases, and it is cheap 329 // compared to computing the covering in the first place. 330 c.result.Normalize() 331 if c.minLevel > 0 || c.levelMod > 1 { 332 c.result.Denormalize(c.minLevel, c.levelMod) 333 } 334 } 335 336 // newCoverer returns an instance of coverer. 337 func (rc *RegionCoverer) newCoverer() *coverer { 338 return &coverer{ 339 minLevel: maxInt(0, minInt(maxLevel, rc.MinLevel)), 340 maxLevel: maxInt(0, minInt(maxLevel, rc.MaxLevel)), 341 levelMod: maxInt(1, minInt(3, rc.LevelMod)), 342 maxCells: rc.MaxCells, 343 } 344 } 345 346 // Covering returns a CellUnion that covers the given region and satisfies the various restrictions. 347 func (rc *RegionCoverer) Covering(region Region) CellUnion { 348 covering := rc.CellUnion(region) 349 covering.Denormalize(maxInt(0, minInt(maxLevel, rc.MinLevel)), maxInt(1, minInt(3, rc.LevelMod))) 350 return covering 351 } 352 353 // InteriorCovering returns a CellUnion that is contained within the given region and satisfies the various restrictions. 354 func (rc *RegionCoverer) InteriorCovering(region Region) CellUnion { 355 intCovering := rc.InteriorCellUnion(region) 356 intCovering.Denormalize(maxInt(0, minInt(maxLevel, rc.MinLevel)), maxInt(1, minInt(3, rc.LevelMod))) 357 return intCovering 358 } 359 360 // CellUnion returns a normalized CellUnion that covers the given region and 361 // satisfies the restrictions except for minLevel and levelMod. These criteria 362 // cannot be satisfied using a cell union because cell unions are 363 // automatically normalized by replacing four child cells with their parent 364 // whenever possible. (Note that the list of cell ids passed to the CellUnion 365 // constructor does in fact satisfy all the given restrictions.) 366 func (rc *RegionCoverer) CellUnion(region Region) CellUnion { 367 c := rc.newCoverer() 368 c.coveringInternal(region) 369 cu := c.result 370 cu.Normalize() 371 return cu 372 } 373 374 // InteriorCellUnion returns a normalized CellUnion that is contained within the given region and 375 // satisfies the restrictions except for minLevel and levelMod. These criteria 376 // cannot be satisfied using a cell union because cell unions are 377 // automatically normalized by replacing four child cells with their parent 378 // whenever possible. (Note that the list of cell ids passed to the CellUnion 379 // constructor does in fact satisfy all the given restrictions.) 380 func (rc *RegionCoverer) InteriorCellUnion(region Region) CellUnion { 381 c := rc.newCoverer() 382 c.interiorCovering = true 383 c.coveringInternal(region) 384 cu := c.result 385 cu.Normalize() 386 return cu 387 } 388 389 // FastCovering returns a CellUnion that covers the given region similar to Covering, 390 // except that this method is much faster and the coverings are not as tight. 391 // All of the usual parameters are respected (MaxCells, MinLevel, MaxLevel, and LevelMod), 392 // except that the implementation makes no attempt to take advantage of large values of 393 // MaxCells. (A small number of cells will always be returned.) 394 // 395 // This function is useful as a starting point for algorithms that 396 // recursively subdivide cells. 397 func (rc *RegionCoverer) FastCovering(region Region) CellUnion { 398 c := rc.newCoverer() 399 cu := CellUnion(region.CellUnionBound()) 400 c.normalizeCovering(&cu) 401 return cu 402 } 403 404 // IsCanonical reports whether the given CellUnion represents a valid covering 405 // that conforms to the current covering parameters. In particular: 406 // 407 // - All CellIDs must be valid. 408 // 409 // - CellIDs must be sorted and non-overlapping. 410 // 411 // - CellID levels must satisfy MinLevel, MaxLevel, and LevelMod. 412 // 413 // - If the covering has more than MaxCells, there must be no two cells with 414 // a common ancestor at MinLevel or higher. 415 // 416 // - There must be no sequence of cells that could be replaced by an 417 // ancestor (i.e. with LevelMod == 1, the 4 child cells of a parent). 418 func (rc *RegionCoverer) IsCanonical(covering CellUnion) bool { 419 return rc.newCoverer().isCanonical(covering) 420 } 421 422 // normalizeCovering normalizes the "covering" so that it conforms to the 423 // current covering parameters (maxCells, minLevel, maxLevel, and levelMod). 424 // This method makes no attempt to be optimal. In particular, if 425 // minLevel > 0 or levelMod > 1 then it may return more than the 426 // desired number of cells even when this isn't necessary. 427 // 428 // Note that when the covering parameters have their default values, almost 429 // all of the code in this function is skipped. 430 func (c *coverer) normalizeCovering(covering *CellUnion) { 431 // If any cells are too small, or don't satisfy levelMod, then replace them with ancestors. 432 if c.maxLevel < maxLevel || c.levelMod > 1 { 433 for i, ci := range *covering { 434 level := ci.Level() 435 newLevel := c.adjustLevel(minInt(level, c.maxLevel)) 436 if newLevel != level { 437 (*covering)[i] = ci.Parent(newLevel) 438 } 439 } 440 } 441 // Sort the cells and simplify them. 442 covering.Normalize() 443 444 // Make sure that the covering satisfies minLevel and levelMod, 445 // possibly at the expense of satisfying MaxCells. 446 if c.minLevel > 0 || c.levelMod > 1 { 447 covering.Denormalize(c.minLevel, c.levelMod) 448 } 449 450 // If there are too many cells and the covering is very large, use the 451 // RegionCoverer to compute a new covering. (This avoids possible O(n^2) 452 // behavior of the simpler algorithm below.) 453 excess := len(*covering) - c.maxCells 454 if excess <= 0 || c.isCanonical(*covering) { 455 return 456 } 457 if excess*len(*covering) > 10000 { 458 rc := NewRegionCoverer() 459 (*covering) = rc.Covering(covering) 460 return 461 } 462 463 // If there are still too many cells, then repeatedly replace two adjacent 464 // cells in CellID order by their lowest common ancestor. 465 for len(*covering) > c.maxCells { 466 bestIndex := -1 467 bestLevel := -1 468 for i := 0; i+1 < len(*covering); i++ { 469 level, ok := (*covering)[i].CommonAncestorLevel((*covering)[i+1]) 470 if !ok { 471 continue 472 } 473 level = c.adjustLevel(level) 474 if level > bestLevel { 475 bestLevel = level 476 bestIndex = i 477 } 478 } 479 480 if bestLevel < c.minLevel { 481 break 482 } 483 484 // Replace all cells contained by the new ancestor cell. 485 id := (*covering)[bestIndex].Parent(bestLevel) 486 (*covering) = c.replaceCellsWithAncestor(*covering, id) 487 488 // Now repeatedly check whether all children of the parent cell are 489 // present, in which case we can replace those cells with their parent. 490 for bestLevel > c.minLevel { 491 bestLevel -= c.levelMod 492 id = id.Parent(bestLevel) 493 if !c.containsAllChildren(*covering, id) { 494 break 495 } 496 (*covering) = c.replaceCellsWithAncestor(*covering, id) 497 } 498 } 499 } 500 501 // isCanonical reports whether the covering is canonical. 502 func (c *coverer) isCanonical(covering CellUnion) bool { 503 trueMax := c.maxLevel 504 if c.levelMod != 1 { 505 trueMax = c.maxLevel - (c.maxLevel-c.minLevel)%c.levelMod 506 } 507 tooManyCells := len(covering) > c.maxCells 508 sameParentCount := 1 509 510 prevID := CellID(0) 511 for _, id := range covering { 512 if !id.IsValid() { 513 return false 514 } 515 516 // Check that the CellID level is acceptable. 517 level := id.Level() 518 if level < c.minLevel || level > trueMax { 519 return false 520 } 521 if c.levelMod > 1 && (level-c.minLevel)%c.levelMod != 0 { 522 return false 523 } 524 525 if prevID != 0 { 526 // Check that cells are sorted and non-overlapping. 527 if prevID.RangeMax() >= id.RangeMin() { 528 return false 529 } 530 531 lev, ok := id.CommonAncestorLevel(prevID) 532 // If there are too many cells, check that no pair of adjacent cells 533 // could be replaced by an ancestor. 534 if tooManyCells && (ok && lev >= c.minLevel) { 535 return false 536 } 537 538 // Check that there are no sequences of (4 ** level_mod) cells that all 539 // have the same parent (considering only multiples of "level_mod"). 540 pLevel := level - c.levelMod 541 if pLevel < c.minLevel || level != prevID.Level() || 542 id.Parent(pLevel) != prevID.Parent(pLevel) { 543 sameParentCount = 1 544 } else { 545 sameParentCount++ 546 if sameParentCount == 1<<uint(2*c.levelMod) { 547 return false 548 } 549 } 550 } 551 prevID = id 552 } 553 554 return true 555 } 556 557 func (c *coverer) containsAllChildren(covering []CellID, id CellID) bool { 558 pos := sort.Search(len(covering), func(i int) bool { return (covering)[i] >= id.RangeMin() }) 559 level := id.Level() + c.levelMod 560 for child := id.ChildBeginAtLevel(level); child != id.ChildEndAtLevel(level); child = child.Next() { 561 if pos == len(covering) || covering[pos] != child { 562 return false 563 } 564 pos++ 565 } 566 return true 567 } 568 569 // replaceCellsWithAncestor replaces all descendants of the given id in covering 570 // with id. This requires the covering contains at least one descendant of id. 571 func (c *coverer) replaceCellsWithAncestor(covering []CellID, id CellID) []CellID { 572 begin := sort.Search(len(covering), func(i int) bool { return covering[i] > id.RangeMin() }) 573 end := sort.Search(len(covering), func(i int) bool { return covering[i] > id.RangeMax() }) 574 575 return append(append(covering[:begin], id), covering[end:]...) 576 } 577 578 // SimpleRegionCovering returns a set of cells at the given level that cover 579 // the connected region and a starting point on the boundary or inside the 580 // region. The cells are returned in arbitrary order. 581 // 582 // Note that this method is not faster than the regular Covering 583 // method for most region types, such as Cap or Polygon, and in fact it 584 // can be much slower when the output consists of a large number of cells. 585 // Currently it can be faster at generating coverings of long narrow regions 586 // such as polylines, but this may change in the future. 587 func SimpleRegionCovering(region Region, start Point, level int) []CellID { 588 return FloodFillRegionCovering(region, cellIDFromPoint(start).Parent(level)) 589 } 590 591 // FloodFillRegionCovering returns all edge-connected cells at the same level as 592 // the given CellID that intersect the given region, in arbitrary order. 593 func FloodFillRegionCovering(region Region, start CellID) []CellID { 594 var output []CellID 595 all := map[CellID]bool{ 596 start: true, 597 } 598 frontier := []CellID{start} 599 for len(frontier) > 0 { 600 id := frontier[len(frontier)-1] 601 frontier = frontier[:len(frontier)-1] 602 if !region.IntersectsCell(CellFromCellID(id)) { 603 continue 604 } 605 output = append(output, id) 606 for _, nbr := range id.EdgeNeighbors() { 607 if !all[nbr] { 608 all[nbr] = true 609 frontier = append(frontier, nbr) 610 } 611 } 612 } 613 614 return output 615 }