| 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 |  |