| 1 | // Copyright 2005 Google Inc. All Rights Reserved. |
| 2 | |
| 3 | #ifndef UTIL_GEOMETRY_S2POLYGON_H_ |
| 4 | #define UTIL_GEOMETRY_S2POLYGON_H_ |
| 5 | |
| 6 | #include <map> |
| 7 | using std::map; |
| 8 | using std::multimap; |
| 9 | |
| 10 | #include <vector> |
| 11 | using std::vector; |
| 12 | |
| 13 | |
| 14 | #include "base/basictypes.h" |
| 15 | #include "base/macros.h" |
| 16 | #include "s2.h" |
| 17 | #include "s2region.h" |
| 18 | #include "s2loop.h" |
| 19 | #include "s2polyline.h" |
| 20 | |
| 21 | class S2CellUnion; |
| 22 | |
| 23 | // An S2Polygon is an S2Region object that represents a polygon. A polygon |
| 24 | // consists of zero or more loops representing "shells" and "holes". All |
| 25 | // loops should be oriented CCW, i.e. the shell or hole is on the left side of |
| 26 | // the loop. Loops may be specified in any order. A point is defined to be |
| 27 | // inside the polygon if it is contained by an odd number of loops. |
| 28 | // |
| 29 | // Polygons have the following restrictions: |
| 30 | // |
| 31 | // - Loops may not cross, i.e. the boundary of a loop may not intersect |
| 32 | // both the interior and exterior of any other loop. |
| 33 | // |
| 34 | // - Loops may not share edges, i.e. if a loop contains an edge AB, then |
| 35 | // no other loop may contain AB or BA. |
| 36 | // |
| 37 | // - No loop may cover more than half the area of the sphere. This ensures |
| 38 | // that no loop properly contains the complement of any other loop, even |
| 39 | // if the loops are from different polygons. (Loops that represent exact |
| 40 | // hemispheres are allowed.) |
| 41 | // |
| 42 | // Loops may share vertices, however no vertex may appear twice in a single |
| 43 | // loop (see s2loop.h). |
| 44 | class S2Polygon : public S2Region { |
| 45 | public: |
| 46 | // Creates an empty polygon that should be initialized by calling Init() or |
| 47 | // Decode(). |
| 48 | S2Polygon(); |
| 49 | |
| 50 | // Convenience constructor that calls Init() with the given loops. Takes |
| 51 | // ownership of the loops and clears the given vector. |
| 52 | explicit S2Polygon(vector<S2Loop*>* loops); |
| 53 | |
| 54 | // Convenience constructor that creates a polygon with a single loop |
| 55 | // corresponding to the given cell. |
| 56 | explicit S2Polygon(S2Cell const& cell); |
| 57 | |
| 58 | // Initialize a polygon by taking ownership of the given loops and clearing |
| 59 | // the given vector. This method figures out the loop nesting hierarchy and |
| 60 | // then reorders the loops by following a preorder traversal. This implies |
| 61 | // that each loop is immediately followed by its descendants in the nesting |
| 62 | // hierarchy. (See also GetParent and GetLastDescendant.) |
| 63 | void Init(vector<S2Loop*>* loops); |
| 64 | |
| 65 | // Release ownership of the loops of this polygon, and appends them to |
| 66 | // "loops" if non-NULL. Resets the polygon to be empty. |
| 67 | void Release(vector<S2Loop*>* loops); |
| 68 | |
| 69 | // Makes a deep copy of the given source polygon. Requires that the |
| 70 | // destination polygon is empty. |
| 71 | void Copy(S2Polygon const* src); |
| 72 | |
| 73 | // Destroys the polygon and frees its loops. |
| 74 | ~S2Polygon(); |
| 75 | |
| 76 | // Return true if the given loops form a valid polygon. Assumes that |
| 77 | // all of the given loops have already been validated. |
| 78 | static bool IsValid(const vector<S2Loop*>& loops); |
| 79 | |
| 80 | // Return true if this is a valid polygon. Note that in debug mode, |
| 81 | // validity is checked at polygon creation time, so IsValid() should always |
| 82 | // return true. |
| 83 | bool IsValid() const; |
| 84 | |
| 85 | // DEPRECATED. |
| 86 | bool IsValid(bool check_loops, int max_adjacent) const; |
| 87 | |
| 88 | int num_loops() const { return loops_.size(); } |
| 89 | |
| 90 | // Total number of vertices in all loops. |
| 91 | int num_vertices() const { return num_vertices_; } |
| 92 | |
| 93 | S2Loop* loop(int k) const { return loops_[k]; } |
| 94 | |
| 95 | // Return the index of the parent of loop k, or -1 if it has no parent. |
| 96 | int GetParent(int k) const; |
| 97 | |
| 98 | // Return the index of the last loop that is contained within loop k. |
| 99 | // Returns num_loops() - 1 if k < 0. Note that loops are indexed according |
| 100 | // to a preorder traversal of the nesting hierarchy, so the immediate |
| 101 | // children of loop k can be found by iterating over loops |
| 102 | // (k+1)..GetLastDescendant(k) and selecting those whose depth is equal to |
| 103 | // (loop(k)->depth() + 1). |
| 104 | int GetLastDescendant(int k) const; |
| 105 | |
| 106 | // Return the area of the polygon interior, i.e. the region on the left side |
| 107 | // of an odd number of loops. The return value is between 0 and 4*Pi. |
| 108 | double GetArea() const; |
| 109 | |
| 110 | // Return the true centroid of the polygon multiplied by the area of the |
| 111 | // polygon (see s2.h for details on centroids). The result is not unit |
| 112 | // length, so you may want to normalize it. Also note that in general, the |
| 113 | // centroid may not be contained by the polygon. |
| 114 | // |
| 115 | // We prescale by the polygon area for two reasons: (1) it is cheaper to |
| 116 | // compute this way, and (2) it makes it easier to compute the centroid of |
| 117 | // more complicated shapes (by splitting them into disjoint regions and |
| 118 | // adding their centroids). |
| 119 | S2Point GetCentroid() const; |
| 120 | |
| 121 | // Return true if this polygon contains the given other polygon, i.e. |
| 122 | // if polygon A contains all points contained by polygon B. |
| 123 | bool Contains(S2Polygon const* b) const; |
| 124 | |
| 125 | // Returns true if this polgyon (A) approximately contains the given other |
| 126 | // polygon (B). This is true if it is possible to move the vertices of B |
| 127 | // no further than "vertex_merge_radius" such that A contains the modified B. |
| 128 | // |
| 129 | // For example, the empty polygon will contain any polygon whose maximum |
| 130 | // width is no more than vertex_merge_radius. |
| 131 | bool ApproxContains(S2Polygon const* b, S1Angle vertex_merge_radius) const; |
| 132 | |
| 133 | // Return true if this polygon intersects the given other polygon, i.e. |
| 134 | // if there is a point that is contained by both polygons. |
| 135 | bool Intersects(S2Polygon const* b) const; |
| 136 | |
| 137 | // Initialize this polygon to the intersection, union, or difference |
| 138 | // (A - B) of the given two polygons. The "vertex_merge_radius" determines |
| 139 | // how close two vertices must be to be merged together and how close a |
| 140 | // vertex must be to an edge in order to be spliced into it (see |
| 141 | // S2PolygonBuilder for details). By default, the merge radius is just |
| 142 | // large enough to compensate for errors that occur when computing |
| 143 | // intersection points between edges (S2EdgeUtil::kIntersectionTolerance). |
| 144 | // |
| 145 | // If you are going to convert the resulting polygon to a lower-precision |
| 146 | // format, it is necessary to increase the merge radius in order to get a |
| 147 | // valid result after rounding (i.e. no duplicate vertices, etc). For |
| 148 | // example, if you are going to convert them to geostore::PolygonProto |
| 149 | // format, then S1Angle::E7(1) is a good value for "vertex_merge_radius". |
| 150 | void InitToIntersection(S2Polygon const* a, S2Polygon const* b); |
| 151 | void InitToIntersectionSloppy(S2Polygon const* a, S2Polygon const* b, |
| 152 | S1Angle vertex_merge_radius); |
| 153 | void InitToUnion(S2Polygon const* a, S2Polygon const* b); |
| 154 | void InitToUnionSloppy(S2Polygon const* a, S2Polygon const* b, |
| 155 | S1Angle vertex_merge_radius); |
| 156 | void InitToDifference(S2Polygon const* a, S2Polygon const* b); |
| 157 | void InitToDifferenceSloppy(S2Polygon const* a, S2Polygon const* b, |
| 158 | S1Angle vertex_merge_radius); |
| 159 | |
| 160 | // Initializes this polygon to a polygon that contains fewer vertices and is |
| 161 | // within tolerance of the polygon a, with some caveats. |
| 162 | // |
| 163 | // - If there is a very small island in the original polygon, it may |
| 164 | // disappear completely. Thus some parts of the original polygon |
| 165 | // may not be close to the simplified polygon. Those parts are small, |
| 166 | // though, and arguably don't need to be kept. |
| 167 | // - However, if there are dense islands, they may all disappear, instead |
| 168 | // of replacing them by a big simplified island. |
| 169 | // - For small tolerances (compared to the polygon size), it may happen that |
| 170 | // the simplified polygon has more vertices than the original, if the |
| 171 | // first step of the simplification creates too many self-intersections. |
| 172 | // One can construct irrealistic cases where that happens to an extreme |
| 173 | // degree. |
| 174 | void InitToSimplified(S2Polygon const* a, S1Angle tolerance); |
| 175 | |
| 176 | // Intersect this polygon with the polyline "in" and append the resulting |
| 177 | // zero or more polylines to "out" (which must be empty). The polylines |
| 178 | // are appended in the order they would be encountered by traversing "in" |
| 179 | // from beginning to end. Note that the output may include polylines with |
| 180 | // only one vertex, but there will not be any zero-vertex polylines. |
| 181 | // |
| 182 | // This is equivalent to calling IntersectWithPolylineSloppy() with the |
| 183 | // "vertex_merge_radius" set to S2EdgeUtil::kIntersectionTolerance. |
| 184 | void IntersectWithPolyline(S2Polyline const* in, |
| 185 | vector<S2Polyline*> *out) const; |
| 186 | |
| 187 | // Similar to IntersectWithPolyline(), except that vertices will be |
| 188 | // dropped as necessary to ensure that all adjacent vertices in the |
| 189 | // sequence obtained by concatenating the output polylines will be |
| 190 | // farther than "vertex_merge_radius" apart. Note that this can change |
| 191 | // the number of output polylines and/or yield single-vertex polylines. |
| 192 | void IntersectWithPolylineSloppy(S2Polyline const* in, |
| 193 | vector<S2Polyline*> *out, |
| 194 | S1Angle vertex_merge_radius) const; |
| 195 | |
| 196 | // Same as IntersectWithPolyline, but subtracts this polygon from |
| 197 | // the given polyline. |
| 198 | void SubtractFromPolyline(S2Polyline const* in, |
| 199 | vector<S2Polyline*> *out) const; |
| 200 | |
| 201 | // Same as IntersectWithPolylineSloppy, but subtracts this polygon |
| 202 | // from the given polyline. |
| 203 | void SubtractFromPolylineSloppy(S2Polyline const* in, |
| 204 | vector<S2Polyline*> *out, |
| 205 | S1Angle vertex_merge_radius) const; |
| 206 | |
| 207 | // Return a polygon which is the union of the given polygons. |
| 208 | // Clears the vector and deletes the polygons! |
| 209 | static S2Polygon* DestructiveUnion(vector<S2Polygon*>* polygons); |
| 210 | static S2Polygon* DestructiveUnionSloppy(vector<S2Polygon*>* polygons, |
| 211 | S1Angle vertex_merge_radius); |
| 212 | |
| 213 | // Initialize this polygon to the outline of the given cell union. |
| 214 | // In principle this polygon should exactly contain the cell union and |
| 215 | // this polygon's inverse should not intersect the cell union, but rounding |
| 216 | // issues may cause this not to be the case. |
| 217 | // Does not work correctly if the union covers more than half the sphere. |
| 218 | void InitToCellUnionBorder(S2CellUnion const& cells); |
| 219 | |
| 220 | // Return true if every loop of this polygon shares at most one vertex with |
| 221 | // its parent loop. Every polygon has a unique normalized form. Normalized |
| 222 | // polygons are useful for testing since it is easy to compare whether two |
| 223 | // polygons represent the same region. |
| 224 | bool IsNormalized() const; |
| 225 | |
| 226 | // Return true if two polygons have the same boundary. More precisely, this |
| 227 | // method requires that both polygons have loops with the same cyclic vertex |
| 228 | // order and the same nesting hierarchy. |
| 229 | bool BoundaryEquals(S2Polygon const* b) const; |
| 230 | |
| 231 | // Return true if two polygons have the same boundary except for vertex |
| 232 | // perturbations. Both polygons must have loops with the same cyclic vertex |
| 233 | // order and the same nesting hierarchy, but the vertex locations are |
| 234 | // allowed to differ by up to "max_error". |
| 235 | bool BoundaryApproxEquals(S2Polygon const* b, double max_error = 1e-15) const; |
| 236 | |
| 237 | // Return true if two polygons have boundaries that are within "max_error" |
| 238 | // of each other along their entire lengths. More precisely, there must be |
| 239 | // a bijection between the two sets of loops such that for each pair of |
| 240 | // loops, "a_loop->BoundaryNear(b_loop)" is true. |
| 241 | bool BoundaryNear(S2Polygon const* b, double max_error = 1e-15) const; |
| 242 | |
| 243 | // If the point is not contained by the polygon returns a point on the |
| 244 | // polygon closest to the given point. Otherwise returns the point itself. |
| 245 | // The polygon must not be empty. |
| 246 | S2Point Project(S2Point const& point) const; |
| 247 | |
| 248 | //////////////////////////////////////////////////////////////////////// |
| 249 | // S2Region interface (see s2region.h for details): |
| 250 | |
| 251 | // GetRectBound() guarantees that it will return exact bounds. GetCapBound() |
| 252 | // does not. |
| 253 | virtual S2Polygon* Clone() const; |
| 254 | virtual S2Cap GetCapBound() const; // Cap surrounding rect bound. |
| 255 | virtual S2LatLngRect GetRectBound() const { return bound_; } |
| 256 | |
| 257 | virtual bool Contains(S2Cell const& cell) const; |
| 258 | virtual bool MayIntersect(S2Cell const& cell) const; |
| 259 | virtual bool VirtualContainsPoint(S2Point const& p) const; |
| 260 | |
| 261 | // The point 'p' does not need to be normalized. |
| 262 | bool Contains(S2Point const& p) const; |
| 263 | |
| 264 | virtual void Encode(Encoder* const encoder) const; |
| 265 | virtual bool Decode(Decoder* const decoder); |
| 266 | virtual bool DecodeWithinScope(Decoder* const decoder); |
| 267 | |
| 268 | private: |
| 269 | // Internal constructor that does *not* take ownership of its argument. |
| 270 | explicit S2Polygon(S2Loop* loop); |
| 271 | |
| 272 | // A map from each loop to its immediate children with respect to nesting. |
| 273 | // This map is built during initialization of multi-loop polygons to |
| 274 | // determine which are shells and which are holes, and then discarded. |
| 275 | typedef map<S2Loop*, vector<S2Loop*> > LoopMap; |
| 276 | |
| 277 | // Internal implementation of the Decode and DecodeWithinScope methods above. |
| 278 | // The within_scope parameter specifies whether to call DecodeWithinScope |
| 279 | // on the loops. |
| 280 | bool DecodeInternal(Decoder* const decoder, bool within_scope); |
| 281 | |
| 282 | // Internal implementation of intersect/subtract polyline functions above. |
| 283 | void InternalClipPolyline(bool invert, |
| 284 | S2Polyline const* a, |
| 285 | vector<S2Polyline*> *out, |
| 286 | S1Angle vertex_merge_radius) const; |
| 287 | |
| 288 | static void InsertLoop(S2Loop* new_loop, S2Loop* parent, LoopMap* loop_map); |
| 289 | static bool ContainsChild(S2Loop* a, S2Loop* b, LoopMap const& loop_map); |
| 290 | void InitLoop(S2Loop* loop, int depth, LoopMap* loop_map); |
| 291 | |
| 292 | int ContainsOrCrosses(S2Loop const* b) const; |
| 293 | bool AnyLoopContains(S2Loop const* b) const; |
| 294 | bool ContainsAllShells(S2Polygon const* b) const; |
| 295 | bool ExcludesAllHoles(S2Polygon const* b) const; |
| 296 | bool IntersectsAnyShell(S2Polygon const* b) const; |
| 297 | bool IntersectsShell(S2Loop const* b) const; |
| 298 | |
| 299 | vector<S2Loop*> loops_; |
| 300 | S2LatLngRect bound_; |
| 301 | char owns_loops_; |
| 302 | char has_holes_; |
| 303 | |
| 304 | // Cache for num_vertices(). |
| 305 | int num_vertices_; |
| 306 | |
| 307 | DISALLOW_EVIL_CONSTRUCTORS(S2Polygon); |
| 308 | }; |
| 309 | |
| 310 | #endif // UTIL_GEOMETRY_S2POLYGON_H_ |
| 311 | |