| 1 | // Copyright 2009 Google Inc. All Rights Reserved. | 
|---|
| 2 |  | 
|---|
| 3 | // Defines the class S2EdgeIndex, a fast lookup structure for edges in S2. | 
|---|
| 4 |  | 
|---|
| 5 | #ifndef UTIL_GEOMETRY_S2EDGEINDEX_H_ | 
|---|
| 6 | #define UTIL_GEOMETRY_S2EDGEINDEX_H_ | 
|---|
| 7 |  | 
|---|
| 8 | #include <map> | 
|---|
| 9 | using std::map; | 
|---|
| 10 | using std::multimap; | 
|---|
| 11 |  | 
|---|
| 12 | #include <utility> | 
|---|
| 13 | using std::pair; | 
|---|
| 14 | using std::make_pair; | 
|---|
| 15 |  | 
|---|
| 16 | #include <vector> | 
|---|
| 17 | using std::vector; | 
|---|
| 18 |  | 
|---|
| 19 |  | 
|---|
| 20 | #include "base/logging.h" | 
|---|
| 21 | #include "base/macros.h" | 
|---|
| 22 | #include "s2cellid.h" | 
|---|
| 23 | #include "s2edgeutil.h" | 
|---|
| 24 |  | 
|---|
| 25 | class S2Cell; | 
|---|
| 26 |  | 
|---|
| 27 | // This class structures a set S of data edges, so that one can quickly | 
|---|
| 28 | // find which edges of S may potentially intersect or touch a query edge. | 
|---|
| 29 | // | 
|---|
| 30 | // The set S is assumed to be indexable by a consecutive sequence of | 
|---|
| 31 | // integers in the range [0..num_edges()-1].  You subclass this class by | 
|---|
| 32 | // defining the three virtual functions num_edges(), edge_from(), | 
|---|
| 33 | // edge_to().  Then you use it as follows for a query edge (a,b): | 
|---|
| 34 | // | 
|---|
| 35 | //   MyS2EdgeIndex edge_index; | 
|---|
| 36 | //   MyS2EdgeIndex::Iterator it(&edge_index); | 
|---|
| 37 | //   S2Point const* from; | 
|---|
| 38 | //   S2Point const* to; | 
|---|
| 39 | //   for (it.GetCandidates(a, b); !it.Done(); it.Next()) { | 
|---|
| 40 | //     edge_index.GetEdge(it.Index(), &from, &to); | 
|---|
| 41 | //     ... RobustCrossing(a,b, from,to) ... | 
|---|
| 42 | //   } | 
|---|
| 43 | // | 
|---|
| 44 | // What is this GetEdge()?  You don't want to use edge_from() and | 
|---|
| 45 | // edge_to() in your own code: these are virtual functions that will | 
|---|
| 46 | // add a lot of overhead.  The most efficient way is as above: you | 
|---|
| 47 | // define GetEdge() in your S2EdgeIndex subclass that access the edge | 
|---|
| 48 | // points as efficiently as possible. | 
|---|
| 49 | // | 
|---|
| 50 | // The function GetCandidates initializes the iterator to return a set | 
|---|
| 51 | // of candidate edges from S, such that we are sure that any data edge | 
|---|
| 52 | // that touches or crosses (a,b) is a candidate. | 
|---|
| 53 | // | 
|---|
| 54 | // This class returns all edges until it finds that it is worth it to compute | 
|---|
| 55 | // a quad tree on the data set.  Chance my have it that you compute the quad | 
|---|
| 56 | // tree exactly when it's too late and all the work is done, If this happens, | 
|---|
| 57 | // we only double the total running time. | 
|---|
| 58 | // | 
|---|
| 59 | // You can help the class by declaring in advance that you will make a | 
|---|
| 60 | // certain number of calls to GetCandidates(): | 
|---|
| 61 | //   MyS2EdgeIndex::Iterator it(&edge_index) | 
|---|
| 62 | //   edge_index.PredictAdditionalCalls(n); | 
|---|
| 63 | //   for (int i = 0; i < n; ++i) { | 
|---|
| 64 | //     for (it.GetCandidates(v(i), v(i+1)); !it.Done(); it.Next()) { | 
|---|
| 65 | //        ... RobustCrossing(v(i), v(i+1), it.From(), it.To()) ... | 
|---|
| 66 | //     } | 
|---|
| 67 | //   } | 
|---|
| 68 | // | 
|---|
| 69 | // Here, we say that we will call GetCandidates() n times.  If we have | 
|---|
| 70 | // 1000 data edges and n=1000, then we will compute the quad tree | 
|---|
| 71 | // immediately instead of waiting till we've wasted enough time to | 
|---|
| 72 | // justify the cost. | 
|---|
| 73 | // | 
|---|
| 74 | // The tradeoff between brute force and quad tree depends on many | 
|---|
| 75 | // things, we use a very approximate trade-off. | 
|---|
| 76 | // | 
|---|
| 77 | // See examples in S2Loop.cc and S2Polygon.cc, in particular, look at | 
|---|
| 78 | // the optimization that allows one to use the EdgeCrosser. | 
|---|
| 79 | // | 
|---|
| 80 | // TODO(user): Get a better API without the clumsy GetCandidates(). | 
|---|
| 81 | //   Maybe edge_index.GetIterator()? | 
|---|
| 82 | class S2EdgeIndex { | 
|---|
| 83 | public: | 
|---|
| 84 | S2EdgeIndex() { Reset(); } | 
|---|
| 85 |  | 
|---|
| 86 | virtual ~S2EdgeIndex() {  } | 
|---|
| 87 |  | 
|---|
| 88 | // An iterator on data edges that may cross a query edge (a,b). | 
|---|
| 89 | // Create the iterator, call GetCandidates(), then Done()/Next() | 
|---|
| 90 | // repeatedly. | 
|---|
| 91 | // | 
|---|
| 92 | // The current edge in the iteration has index Index(), goes between | 
|---|
| 93 | // From() and To(). | 
|---|
| 94 | class Iterator { | 
|---|
| 95 | public: | 
|---|
| 96 | explicit Iterator(S2EdgeIndex* edge_index): edge_index_(edge_index) {} | 
|---|
| 97 |  | 
|---|
| 98 | // Initializes the iterator to iterate over a set of candidates that may | 
|---|
| 99 | // cross the edge (a,b). | 
|---|
| 100 | void GetCandidates(S2Point const& a, S2Point const& b); | 
|---|
| 101 |  | 
|---|
| 102 | // Index of the current edge in the iteration. | 
|---|
| 103 | int Index() const; | 
|---|
| 104 |  | 
|---|
| 105 | // True if there is no more candidate. | 
|---|
| 106 | bool Done() const; | 
|---|
| 107 |  | 
|---|
| 108 | // Iterate to the next available candidate. | 
|---|
| 109 | void Next(); | 
|---|
| 110 |  | 
|---|
| 111 | private: | 
|---|
| 112 | // The structure containing the data edges. | 
|---|
| 113 | S2EdgeIndex* edge_index_; | 
|---|
| 114 |  | 
|---|
| 115 | // Tells whether GetCandidates() obtained the candidates through brute | 
|---|
| 116 | // force iteration or using the quad tree structure. | 
|---|
| 117 | bool is_brute_force_; | 
|---|
| 118 |  | 
|---|
| 119 | // Index of the current edge and of the edge before the last Next() call. | 
|---|
| 120 | int current_index_; | 
|---|
| 121 |  | 
|---|
| 122 | // Cache of edge_index_->num_edges() so that Done() doesn't call a virtual | 
|---|
| 123 | int num_edges_; | 
|---|
| 124 |  | 
|---|
| 125 | // All the candidates obtained by GetCandidates() when we are | 
|---|
| 126 | // using a quad-tree (i.e. is_brute_force = false). | 
|---|
| 127 | vector<int> candidates_; | 
|---|
| 128 |  | 
|---|
| 129 | // Index within array above. | 
|---|
| 130 | // We have: current_index_ = candidates_[current_index_in_candidates_]. | 
|---|
| 131 | int current_index_in_candidates_; | 
|---|
| 132 |  | 
|---|
| 133 | DISALLOW_COPY_AND_ASSIGN(Iterator); | 
|---|
| 134 | }; | 
|---|
| 135 |  | 
|---|
| 136 | // Empties the index in case it already contained something. | 
|---|
| 137 | void Reset(); | 
|---|
| 138 |  | 
|---|
| 139 | // Computes the index if not yet done and tells if the index has | 
|---|
| 140 | // been computed. | 
|---|
| 141 | void ComputeIndex(); | 
|---|
| 142 | bool IsIndexComputed() const; | 
|---|
| 143 |  | 
|---|
| 144 | // If the index hasn't been computed yet, looks at how much work has | 
|---|
| 145 | // gone into iterating using the brute force method, and how much | 
|---|
| 146 | // more work is planned as defined by 'cost'.  If it were to have been | 
|---|
| 147 | // cheaper to use a quad tree from the beginning, then compute it | 
|---|
| 148 | // now.  This guarantees that we will never use more than twice the | 
|---|
| 149 | // time we would have used had we known in advance exactly how many | 
|---|
| 150 | // edges we would have wanted to test.  It is the theoretical best. | 
|---|
| 151 | // | 
|---|
| 152 | // The value 'n' is the number of iterators we expect to request from | 
|---|
| 153 | // this edge index. | 
|---|
| 154 | void PredictAdditionalCalls(int n); | 
|---|
| 155 |  | 
|---|
| 156 | // Overwrite these functions to give access to the underlying data. | 
|---|
| 157 | // The function num_edges() returns the number of edges in the | 
|---|
| 158 | // index, while edge_from(index) and edge_to(index) return the | 
|---|
| 159 | // "from" and "to" endpoints of the edge at the given index. | 
|---|
| 160 | virtual int num_edges() const = 0; | 
|---|
| 161 | virtual S2Point const* edge_from(int index) const = 0; | 
|---|
| 162 | virtual S2Point const* edge_to(int index) const = 0; | 
|---|
| 163 |  | 
|---|
| 164 | protected: | 
|---|
| 165 | // Appends to result all edge references in the map that cross the | 
|---|
| 166 | // query edge, and possibly some more. | 
|---|
| 167 | void FindCandidateCrossings(S2Point const& a, S2Point const& b, | 
|---|
| 168 | vector<int>* result) const; | 
|---|
| 169 |  | 
|---|
| 170 | // Tell the index that we just received a new request for candidates. | 
|---|
| 171 | // Useful to compute when to switch to quad tree. | 
|---|
| 172 | void IncrementQueryCount(); | 
|---|
| 173 |  | 
|---|
| 174 | private: | 
|---|
| 175 | typedef multimap<S2CellId, int> CellEdgeMultimap; | 
|---|
| 176 |  | 
|---|
| 177 | // Inserts the given directed edge into the quad tree. | 
|---|
| 178 | void Insert(S2Point const& a, S2Point const& b, int reference); | 
|---|
| 179 |  | 
|---|
| 180 | // Computes a cell covering of an edge.  Returns the level of the s2 cells | 
|---|
| 181 | // used in the covering (only one level is ever used for each call). | 
|---|
| 182 | // | 
|---|
| 183 | // If thicken_edge is true, the edge is thickened and extended | 
|---|
| 184 | // by 1% of its length. | 
|---|
| 185 | // | 
|---|
| 186 | // It is guaranteed that no child of a covering cell will fully contain | 
|---|
| 187 | // the covered edge. | 
|---|
| 188 | int GetCovering(S2Point const& a, S2Point const& b, | 
|---|
| 189 | bool thicken_edge, | 
|---|
| 190 | vector<S2CellId>* result) const; | 
|---|
| 191 |  | 
|---|
| 192 | // Adds to candidate_crossings all the edges present in any ancestor of any | 
|---|
| 193 | // cell of cover, down to minimum_s2_level_used.  The cell->edge map | 
|---|
| 194 | // is in the variable mapping. | 
|---|
| 195 | static void GetEdgesInParentCells( | 
|---|
| 196 | const vector<S2CellId>& cover, | 
|---|
| 197 | const CellEdgeMultimap& mapping, | 
|---|
| 198 | int minimum_s2_level_used, | 
|---|
| 199 | vector<int>* candidate_crossings); | 
|---|
| 200 |  | 
|---|
| 201 | // Returns true if the edge and the cell (including boundary) intersect. | 
|---|
| 202 | static bool EdgeIntersectsCellBoundary( | 
|---|
| 203 | S2Point const& a, S2Point const& b, | 
|---|
| 204 | const S2Cell& cell); | 
|---|
| 205 |  | 
|---|
| 206 | // Appends to candidate_crossings the edges that are fully contained in an | 
|---|
| 207 | // S2 covering of edge.  The covering of edge used is initially cover, but | 
|---|
| 208 | // is refined to eliminate quickly subcells that contain many edges but do | 
|---|
| 209 | // not intersect with edge. | 
|---|
| 210 | static void GetEdgesInChildrenCells( | 
|---|
| 211 | S2Point const& a, S2Point const& b, | 
|---|
| 212 | vector<S2CellId>* cover, | 
|---|
| 213 | const CellEdgeMultimap& mapping, | 
|---|
| 214 | vector<int>* candidate_crossings); | 
|---|
| 215 |  | 
|---|
| 216 | // Maps cell ids to covered edges; has the property that the set of all cell | 
|---|
| 217 | // ids mapping to a particular edge forms a covering of that edge. | 
|---|
| 218 | CellEdgeMultimap mapping_; | 
|---|
| 219 |  | 
|---|
| 220 | // No cell strictly below this level appears in mapping_.  Initially leaf | 
|---|
| 221 | // level, that's the minimum level at which we will ever look for test edges. | 
|---|
| 222 | int minimum_s2_level_used_; | 
|---|
| 223 |  | 
|---|
| 224 | // Has the index been computed already? | 
|---|
| 225 | bool index_computed_; | 
|---|
| 226 |  | 
|---|
| 227 | // Number of queries so far | 
|---|
| 228 | int query_count_; | 
|---|
| 229 |  | 
|---|
| 230 | DISALLOW_COPY_AND_ASSIGN(S2EdgeIndex); | 
|---|
| 231 | }; | 
|---|
| 232 |  | 
|---|
| 233 | inline bool S2EdgeIndex::Iterator::Done() const { | 
|---|
| 234 | if (is_brute_force_) { | 
|---|
| 235 | return (current_index_ >= num_edges_); | 
|---|
| 236 | } else { | 
|---|
| 237 | return size_t(current_index_in_candidates_) >= candidates_.size(); | 
|---|
| 238 | } | 
|---|
| 239 | } | 
|---|
| 240 |  | 
|---|
| 241 | inline int S2EdgeIndex::Iterator::Index() const { | 
|---|
| 242 | DCHECK(!Done()); | 
|---|
| 243 | return current_index_; | 
|---|
| 244 | } | 
|---|
| 245 |  | 
|---|
| 246 | inline void S2EdgeIndex::Iterator::Next() { | 
|---|
| 247 | DCHECK(!Done()); | 
|---|
| 248 | if (is_brute_force_) { | 
|---|
| 249 | current_index_++; | 
|---|
| 250 | } else { | 
|---|
| 251 | current_index_in_candidates_++; | 
|---|
| 252 | if (size_t(current_index_in_candidates_) < candidates_.size()) { | 
|---|
| 253 | current_index_ = candidates_[current_index_in_candidates_]; | 
|---|
| 254 | } | 
|---|
| 255 | } | 
|---|
| 256 | } | 
|---|
| 257 |  | 
|---|
| 258 | #endif  // UTIL_GEOMETRY_S2EDGEINDEX_H_ | 
|---|
| 259 |  | 
|---|