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 // A RegionUnion represents a union of possibly overlapping regions. It is 18 // convenient for computing a covering of a set of regions. However, note 19 // that currently, using RegionCoverer to compute coverings of RegionUnions 20 // may produce coverings with considerably less than the requested number of 21 // cells in cases of overlapping or tiling regions. This occurs because the 22 // current RegionUnion.Contains implementation for Cells only returns 23 // true if the cell is fully contained by one of the regions. So, cells along 24 // internal boundaries in the region union will be subdivided by the coverer 25 // even though this is unnecessary, using up the maxSize cell budget. Then, 26 // when the coverer normalizes the covering, groups of 4 sibling cells along 27 // these internal borders will be replaced by parents, resulting in coverings 28 // that may have significantly fewer than maxSize cells, and so are less 29 // accurate. This is not a concern for unions of disjoint regions. 30 type RegionUnion []Region 31 32 // CapBound returns a bounding cap for this RegionUnion. 33 func (ru RegionUnion) CapBound() Cap { return ru.RectBound().CapBound() } 34 35 // RectBound returns a bounding latitude-longitude rectangle for this RegionUnion. 36 func (ru RegionUnion) RectBound() Rect { 37 ret := EmptyRect() 38 for _, reg := range ru { 39 ret = ret.Union(reg.RectBound()) 40 } 41 return ret 42 } 43 44 // ContainsCell reports whether the given Cell is contained by this RegionUnion. 45 // 46 // The current implementation only returns true if one of the regions in the 47 // union fully contains the cell. 48 func (ru RegionUnion) ContainsCell(c Cell) bool { 49 for _, reg := range ru { 50 if reg.ContainsCell(c) { 51 return true 52 } 53 } 54 return false 55 } 56 57 // IntersectsCell reports whether this RegionUnion intersects the given cell. 58 func (ru RegionUnion) IntersectsCell(c Cell) bool { 59 for _, reg := range ru { 60 if reg.IntersectsCell(c) { 61 return true 62 } 63 } 64 return false 65 } 66 67 // ContainsPoint reports whether this RegionUnion contains the Point. 68 func (ru RegionUnion) ContainsPoint(p Point) bool { 69 for _, reg := range ru { 70 if reg.ContainsPoint(p) { 71 return true 72 } 73 } 74 return false 75 } 76 77 // CellUnionBound computes a covering of the RegionUnion. 78 func (ru RegionUnion) CellUnionBound() []CellID { 79 return ru.CapBound().CellUnionBound() 80 } 81