1 // Copyright 2013 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 16 // Original Author: ericv@google.com (Eric Veach) 17 // Converted to D: madric@gmail.com (Vijay Nayar) 18 19 module s2.shapeutil.range_iterator; 20 21 import s2.s2cell_id; 22 import s2.s2shape_index; 23 24 // RangeIterator is a wrapper over S2ShapeIndex::Iterator with extra methods 25 // that are useful for merging the contents of two or more S2ShapeIndexes. 26 class RangeIterator { 27 private: 28 // Updates internal state after the iterator has been repositioned. 29 void refresh() { 30 _rangeMin = id().rangeMin(); 31 _rangeMax = id().rangeMax(); 32 } 33 34 S2ShapeIndex.Iterator _it; 35 S2CellId _rangeMin, _rangeMax; 36 37 public: 38 // Construct a new RangeIterator positioned at the first cell of the index. 39 this(S2ShapeIndex index) { 40 _it = new S2ShapeIndex.Iterator(index, S2ShapeIndex.InitialPosition.BEGIN); 41 refresh(); 42 } 43 44 // The current S2CellId and cell contents. 45 S2CellId id() const { 46 return _it.id(); 47 } 48 49 const(S2ShapeIndexCell) cell() const { 50 return _it.cell(); 51 } 52 53 // The min and max leaf cell ids covered by the current cell. If done() is 54 // true, these methods return a value larger than any valid cell id. 55 S2CellId rangeMin() const { 56 return _rangeMin; 57 } 58 S2CellId rangeMax() const { 59 return _rangeMax; 60 } 61 62 void next() { 63 _it.next(); 64 refresh(); 65 } 66 67 bool done() { 68 return _it.done(); 69 } 70 71 // Position the iterator at the first cell that overlaps or follows 72 // "target", i.e. such that range_max() >= target.range_min(). 73 void seekTo(in RangeIterator target) { 74 _it.seek(target.rangeMin()); 75 // If the current cell does not overlap "target", it is possible that the 76 // previous cell is the one we are looking for. This can only happen when 77 // the previous cell contains "target" but has a smaller S2CellId. 78 if (_it.done() || _it.id().rangeMin() > target.rangeMax()) { 79 if (_it.prev() && _it.id().rangeMax() < target.id()) _it.next(); 80 } 81 refresh(); 82 } 83 84 // Position the iterator at the first cell that follows "target", i.e. the 85 // first cell such that range_min() > target.range_max(). 86 void seekBeyond(in RangeIterator target) { 87 _it.seek(target.rangeMax().next()); 88 if (!_it.done() && _it.id().rangeMin() <= target.rangeMax()) { 89 _it.next(); 90 } 91 refresh(); 92 } 93 94 }