1 /** 2 An S2Polygon is an S2Region object that represents a polygon. 3 4 Copyright: 2005 Google Inc. All Rights Reserved. 5 6 License: 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 $(LINK http://www.apache.org/licenses/LICENSE-2.0) 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS-IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 Authors: ericv@google.com (Eric Veach), madric@gmail.com (Vijay Nayar) 20 */ 21 module s2.s2polygon; 22 23 import s2.builder.util.s2polygon_layer; 24 import s2.builder.util.s2polyline_layer; 25 import s2.builder.util.s2polyline_vector_layer; 26 import s2.builder.util.snap_functions; 27 import s2.logger; 28 import s2.mutable_s2shape_index; 29 import s2.r2point; 30 import s2.r2rect; 31 import s2.s1angle; 32 import s2.s2boolean_operation; 33 import s2.s2builder; 34 import s2.s2cap; 35 import s2.s2cell; 36 import s2.s2cell_id; 37 import s2.s2cell_union; 38 import s2.s2contains_point_query; 39 import s2.s2coords : MAX_CELL_LEVEL; 40 import s2.s2debug; 41 import s2.s2edge_crossings : INTERSECTION_ERROR, INTERSECTION_MERGE_RADIUS; 42 import s2.s2error; 43 import s2.s2latlng_rect; 44 import s2.s2latlng_rect_bounder; 45 import s2.s2loop; 46 import s2.s2metrics; 47 import s2.s2point; 48 import s2.s2point_compression; 49 import s2.s2polyline; 50 import s2.s2region; 51 import s2.s2shape; 52 import s2.s2shape_index; 53 import s2.s2shape_index_region : makeS2ShapeIndexRegion; 54 import s2.util.coding.coder; 55 import s2.util.container.btree_map; 56 57 import core.atomic; 58 import std.algorithm; 59 import std.container.rbtree; 60 import std.conv; 61 import std.exception; 62 import std.math; 63 import std.range; 64 import std.typecons; 65 66 /** 67 * Build the S2ShapeIndex only when it is first needed. This can save 68 * significant amounts of memory and time when geometry is constructed but 69 * never queried, for example when converting from one format to another. 70 */ 71 enum bool S2POLYGON_LAZY_INDEXING = true; 72 73 /** 74 * An S2Polygon is an S2Region object that represents a polygon. A polygon is 75 * defined by zero or more loops; recall that the interior of a loop is 76 * defined to be its left-hand side (see S2Loop). There are two different 77 * conventions for creating an S2Polygon: 78 * 79 * - InitNested() expects the input loops to be nested hierarchically. The 80 * polygon interior then consists of the set of points contained by an odd 81 * number of loops. So for example, a circular region with a hole in it 82 * would be defined as two CCW loops, with one loop containing the other. 83 * The loops can be provided in any order. 84 * 85 * When the orientation of the input loops is unknown, the nesting 86 * requirement is typically met by calling S2Loop::Normalize() on each 87 * loop (which inverts the loop if necessary so that it encloses at most 88 * half the sphere). But in fact any set of loops can be used as long as 89 * (1) there is no pair of loops that cross, and (2) there is no pair of 90 * loops whose union is the entire sphere. 91 * 92 * - InitOriented() expects the input loops to be oriented such that the 93 * polygon interior is on the left-hand side of every loop. So for 94 * example, a circular region with a hole in it would be defined using a 95 * CCW outer loop and a CW inner loop. The loop orientations must all be 96 * consistent; for example, it is not valid to have one CCW loop nested 97 * inside another CCW loop, because the region between the two loops is on 98 * the left-hand side of one loop and the right-hand side of the other. 99 * 100 * Most clients will not call these methods directly; instead they should use 101 * S2Builder, which has better support for dealing with imperfect data. 102 * 103 * When the polygon is initialized, the given loops are automatically 104 * converted into a canonical form consisting of "shells" and "holes". Shells 105 * and holes are both oriented CCW, and are nested hierarchically. The loops 106 * are reordered to correspond to a preorder traversal of the nesting 107 * hierarchy; InitOriented may also invert some loops. The set of input S2Loop 108 * pointers is always preserved; the caller can use this to determine how the 109 * loops were reordered if desired. 110 * 111 * Polygons may represent any region of the sphere with a polygonal boundary, 112 * including the entire sphere (known as the "full" polygon). The full 113 * polygon consists of a single full loop (see S2Loop), whereas the empty 114 * polygon has no loops at all. 115 * 116 * Polygons have the following restrictions: 117 * 118 * - Loops may not cross, i.e. the boundary of a loop may not intersect 119 * both the interior and exterior of any other loop. 120 * 121 * - Loops may not share edges, i.e. if a loop contains an edge AB, then 122 * no other loop may contain AB or BA. 123 * 124 * - Loops may share vertices, however no vertex may appear twice in a 125 * single loop (see S2Loop). 126 * 127 * - No loop may be empty. The full loop may appear only in the full polygon. 128 */ 129 class S2Polygon : S2Region { 130 public: 131 /** 132 * The default constructor creates an empty polygon. It can be made 133 * non-empty by calling Init(), Decode(), etc. 134 */ 135 this() { 136 _bound = new S2LatLngRect(); 137 _subregionBound = new S2LatLngRect(); 138 _index = new MutableS2ShapeIndex(); 139 _s2debugOverride = S2Debug.ALLOW; 140 _errorInconsistentLoopOrientations = false; 141 _numVertices = 0; 142 _unindexedContainsCalls = 0; 143 } 144 145 /** 146 * Convenience constructor that calls InitNested() with the given loops. 147 * 148 * When called with override == S2Debug::ALLOW, the automatic validity 149 * checking is controlled by --s2debug (which is true by default in 150 * non-optimized builds). When this flag is enabled, a fatal error is 151 * generated whenever an invalid polygon is constructed. 152 * 153 * With override == S2Debug::DISABLE, the automatic validity checking 154 * is disabled. The main reason to do this is if you intend to call 155 * IsValid() explicitly. (See set_s2debug_override() for details.) 156 * Example: 157 * 158 * S2Polygon* polygon = new S2Polygon(loops, S2Debug::DISABLE); 159 * 160 * This is equivalent to: 161 * 162 * S2Polygon* polygon = new S2Polygon; 163 * polygon->set_s2debug_override(S2Debug::DISABLE); 164 * polygon->InitNested(loops); 165 */ 166 this(S2Loop[] loops, S2Debug s2debugOverride = S2Debug.ALLOW) { 167 _bound = new S2LatLngRect(); 168 _subregionBound = new S2LatLngRect(); 169 _index = new MutableS2ShapeIndex(); 170 _s2debugOverride = s2debugOverride; 171 initializeNested(loops); 172 } 173 174 /** 175 * Convenience constructor that creates a polygon with a single loop 176 * corresponding to the given cell. 177 */ 178 this(in S2Cell cell) { 179 _bound = new S2LatLngRect(); 180 _subregionBound = new S2LatLngRect(); 181 _index = new MutableS2ShapeIndex(); 182 _s2debugOverride = S2Debug.ALLOW; 183 initialize(new S2Loop(cell)); 184 } 185 186 /** 187 * Convenience constructor that calls Init(S2Loop*). Note that this method 188 * automatically converts the special empty loop (see S2Loop) into an empty 189 * polygon, unlike the vector-of-loops constructor which does not allow 190 * empty loops at all. 191 */ 192 this(S2Loop loop, S2Debug s2debugOverride = S2Debug.ALLOW) { 193 _bound = new S2LatLngRect(); 194 _subregionBound = new S2LatLngRect(); 195 _index = new MutableS2ShapeIndex(); 196 _s2debugOverride = s2debugOverride; 197 initialize(loop); 198 } 199 200 /** 201 * Create a polygon from a set of hierarchically nested loops. The polygon 202 * interior consists of the points contained by an odd number of loops. 203 * (Recall that a loop contains the set of points on its left-hand side.) 204 * 205 * This method figures out the loop nesting hierarchy and assigns every 206 * loop a depth. Shells have even depths, and holes have odd depths. Note 207 * that the loops are reordered so the hierarchy can be traversed more 208 * easily (see GetParent(), GetLastDescendant(), and S2Loop::depth()). 209 * 210 * This method may be called more than once, in which case any existing 211 * loops are deleted before being replaced by the input loops. 212 */ 213 void initializeNested(S2Loop[] loops) { 214 clearLoops(); 215 _loops = loops; 216 217 if (numLoops() == 1) { 218 initializeOneLoop(); 219 return; 220 } 221 LoopMap loop_map; 222 foreach (int i; 0 .. numLoops()) { 223 insertLoop(loop(i), null, loop_map); 224 } 225 _loops.length = 0; 226 initializeLoops(loop_map); 227 228 // Compute num_vertices_, bound_, subregion_bound_. 229 initializeLoopProperties(); 230 } 231 232 /** 233 * Like InitNested(), but expects loops to be oriented such that the polygon 234 * interior is on the left-hand side of all loops. This implies that shells 235 * and holes should have opposite orientations in the input to this method. 236 * (During initialization, loops representing holes will automatically be 237 * inverted.) 238 */ 239 void initializeOriented(S2Loop[] loops) { 240 // Here is the algorithm: 241 // 242 // 1. Remember which of the given loops contain S2::Origin(). 243 // 244 // 2. Invert loops as necessary to ensure that they are nestable (i.e., no 245 // loop contains the complement of any other loop). This may result in a 246 // set of loops corresponding to the complement of the given polygon, but 247 // we will fix that problem later. 248 // 249 // We make the loops nestable by first normalizing all the loops (i.e., 250 // inverting any loops whose turning angle is negative). This handles 251 // all loops except those whose turning angle is very close to zero 252 // (within the maximum error tolerance). Any such loops are inverted if 253 // and only if they contain S2::Origin(). (In theory this step is only 254 // necessary if there are at least two such loops.) The resulting set of 255 // loops is guaranteed to be nestable. 256 // 257 // 3. Build the polygon. This yields either the desired polygon or its 258 // complement. 259 // 260 // 4. If there is at least one loop, we find a loop L that is adjacent to 261 // S2::Origin() (where "adjacent" means that there exists a path 262 // connecting S2::Origin() to some vertex of L such that the path does 263 // not cross any loop). There may be a single such adjacent loop, or 264 // there may be several (in which case they should all have the same 265 // contains_origin() value). We choose L to be the loop containing the 266 // origin whose depth is greatest, or loop(0) (a top-level shell) if no 267 // such loop exists. 268 // 269 // 5. If (L originally contained origin) != (polygon contains origin), we 270 // invert the polygon. This is done by inverting a top-level shell whose 271 // turning angle is minimal and then fixing the nesting hierarchy. Note 272 // that because we normalized all the loops initially, this step is only 273 // necessary if the polygon requires at least one non-normalized loop to 274 // represent it. 275 276 bool[S2Loop] contained_origin; 277 for (int i = 0; i < loops.length; ++i) { 278 S2Loop loop = loops[i]; 279 if (loop.containsOrigin()) { 280 contained_origin[loop] = true; 281 } 282 double angle = loop.getTurningAngle(); 283 if (fabs(angle) > loop.getTurningAngleMaxError()) { 284 // Normalize the loop. 285 if (angle < 0) loop.invert(); 286 } else { 287 // Ensure that the loop does not contain the origin. 288 if (loop.containsOrigin()) loop.invert(); 289 } 290 } 291 initializeNested(loops); 292 if (numLoops() > 0) { 293 S2Loop origin_loop = loop(0); 294 bool polygon_contains_origin = false; 295 for (int i = 0; i < numLoops(); ++i) { 296 if (loop(i).containsOrigin()) { 297 polygon_contains_origin ^= true; 298 origin_loop = loop(i); 299 } 300 } 301 if (contained_origin.get(origin_loop, false) != polygon_contains_origin) { 302 invert(); 303 } 304 } 305 // Verify that the original loops had consistent shell/hole orientations. 306 // Each original loop L should have been inverted if and only if it now 307 // represents a hole. 308 for (int i = 0; i < _loops.length; ++i) { 309 if ((contained_origin.get(loop(i), false) != loop(i).containsOrigin()) 310 != loop(i).isHole()) { 311 // There is no point in saving the loop index, because the error is a 312 // property of the entire set of loops. In general there is no way to 313 // determine which ones are incorrect. 314 _errorInconsistentLoopOrientations = true; 315 if (flagsS2Debug && _s2debugOverride == S2Debug.ALLOW) { 316 // The FLAGS_s2debug validity checking usually happens in InitIndex(), 317 // but this error is detected too late for that. 318 enforce(isValid()); // Always fails. 319 } 320 } 321 } 322 } 323 324 /** 325 * Initialize a polygon from a single loop. Note that this method 326 * automatically converts the special empty loop (see S2Loop) into an empty 327 * polygon, unlike the vector-of-loops InitNested() method which does not 328 * allow empty loops at all. 329 */ 330 void initialize(S2Loop loop) { 331 // We don't allow empty loops in the other Init() methods because deleting 332 // them changes the number of loops, which is awkward to handle. 333 clearLoops(); 334 if (loop.isEmpty()) { 335 initializeLoopProperties(); 336 } else { 337 _loops ~= loop; 338 initializeOneLoop(); 339 } 340 } 341 342 /** 343 * Releases ownership of and returns the loops of this polygon, and resets 344 * the polygon to be empty. 345 */ 346 S2Loop[] release() { 347 // Reset the polygon to be empty. 348 S2Loop[] loops; 349 loops.swap(_loops); 350 clearLoops(); 351 _numVertices = 0; 352 _bound = S2LatLngRect.empty(); 353 _subregionBound = S2LatLngRect.empty(); 354 return loops; 355 } 356 357 // Makes a deep copy of the given source polygon. The destination polygon 358 // will be cleared if necessary. 359 void copy(in S2Polygon src) { 360 clearLoops(); 361 for (int i = 0; i < src.numLoops(); ++i) { 362 _loops ~= src.loop(i).clone(); 363 } 364 _s2debugOverride = src._s2debugOverride; 365 // Don't copy error_inconsistent_loop_orientations_, since this is not a 366 // property of the polygon but only of the way the polygon was constructed. 367 _numVertices = src.numVertices(); 368 atomicStore!(MemoryOrder.raw)(_unindexedContainsCalls, 0); 369 _bound = new S2LatLngRect(src._bound); 370 _subregionBound = new S2LatLngRect(src._subregionBound); 371 initializeIndex(); // TODO(ericv): Copy the index efficiently. 372 } 373 374 /// Destroys the polygon and frees its loops. 375 // ~this() { 376 // clearLoops(); 377 // } 378 379 /** 380 * Allows overriding the automatic validity checks controlled by 381 * --s2debug (which is true by default in non-optimized builds). 382 * When this flag is enabled, a fatal error is generated whenever 383 * an invalid polygon is constructed. The main reason to disable 384 * this flag is if you intend to call IsValid() explicitly, like this: 385 * 386 * S2Polygon polygon; 387 * polygon.set_s2debug_override(S2Debug::DISABLE); 388 * polygon.Init(...); 389 * if (!polygon.IsValid()) { ... } 390 * 391 * This setting is preserved across calls to Init() and Decode(). 392 */ 393 void setS2debugOverride(S2Debug s2debugOverride) { 394 _s2debugOverride = s2debugOverride; 395 } 396 S2Debug s2debugOverride() const { 397 return _s2debugOverride; 398 } 399 400 /** 401 * Returns true if this is a valid polygon (including checking whether all 402 * the loops are themselves valid). Note that validity is checked 403 * automatically during initialization when --s2debug is enabled (true by 404 * default in debug binaries). 405 */ 406 bool isValid() { 407 S2Error error; 408 if (findValidationError(error) && flagsS2Debug) { 409 logger.logError(error); 410 return false; 411 } 412 return true; 413 } 414 415 /** 416 * Returns true if this is *not* a valid polygon and sets "error" 417 * appropriately. Otherwise returns false and leaves "error" unchanged. 418 * 419 * Note that in error messages, loops that represent holes have their edges 420 * numbered in reverse order, starting from the last vertex of the loop. 421 * 422 * REQUIRES: error != nullptr 423 */ 424 bool findValidationError(out S2Error error) { 425 import s2.shapeutil.visit_crossing_edge_pairs : findSelfIntersection; 426 427 for (int i = 0; i < numLoops(); ++i) { 428 // Check for loop errors that don't require building an S2ShapeIndex. 429 if (loop(i).findValidationErrorNoIndex(error)) { 430 error.initialize(error.code(), "Loop %d: %s", i, error.text()); 431 return true; 432 } 433 // Check that no loop is empty, and that the full loop only appears in the 434 // full polygon. 435 if (loop(i).isEmpty()) { 436 error.initialize(S2Error.Code.POLYGON_EMPTY_LOOP, "Loop %d: empty loops are not allowed", i); 437 return true; 438 } 439 if (loop(i).isFull() && numLoops() > 1) { 440 error.initialize( 441 S2Error.Code.POLYGON_EXCESS_FULL_LOOP, "Loop %d: full loop appears in non-full polygon", i); 442 return true; 443 } 444 } 445 446 // Check for loop self-intersections and loop pairs that cross 447 // (including duplicate edges and vertices). 448 if (findSelfIntersection(_index, error)) return true; 449 450 // Check whether InitOriented detected inconsistent loop orientations. 451 if (_errorInconsistentLoopOrientations) { 452 error.initialize(S2Error.Code.POLYGON_INCONSISTENT_LOOP_ORIENTATIONS, 453 "Inconsistent loop orientations detected"); 454 return true; 455 } 456 457 // Finally, verify the loop nesting hierarchy. 458 return findLoopNestingError(error); 459 } 460 461 /// Return true if this is the empty polygon (consisting of no loops). 462 bool isEmpty() const { 463 return _loops.empty(); 464 } 465 466 /** 467 * Return true if this is the full polygon (consisting of a single loop that 468 * encompasses the entire sphere). 469 */ 470 bool isFull() const { 471 return numLoops() == 1 && loop(0).isFull(); 472 } 473 474 /// Return the number of loops in this polygon. 475 int numLoops() const { 476 return cast(int)(_loops.length); 477 } 478 479 /// Total number of vertices in all loops. 480 int numVertices() const { 481 return _numVertices; 482 } 483 484 // Return the loop at the given index. Note that during initialization, the 485 // given loops are reordered according to a preorder traversal of the loop 486 // nesting hierarchy. This implies that every loop is immediately followed 487 // by its descendants. This hierarchy can be traversed using the methods 488 // GetParent(), GetLastDescendant(), and S2Loop::depth(). 489 inout(S2Loop) loop(int k) inout { 490 return _loops[k]; 491 } 492 493 /// Return the index of the parent of loop k, or -1 if it has no parent. 494 int getParent(int k) const { 495 int depth = loop(k).depth(); 496 if (depth == 0) return -1; // Optimization. 497 while (--k >= 0 && loop(k).depth() >= depth) continue; 498 return k; 499 } 500 501 /** 502 * Return the index of the last loop that is contained within loop k. 503 * Returns num_loops() - 1 if k < 0. Note that loops are indexed according 504 * to a preorder traversal of the nesting hierarchy, so the immediate 505 * children of loop k can be found by iterating over loops 506 * (k+1)..GetLastDescendant(k) and selecting those whose depth is equal to 507 * (loop(k)->depth() + 1). 508 */ 509 int getLastDescendant(int k) const { 510 if (k < 0) return numLoops() - 1; 511 int depth = loop(k).depth(); 512 while (++k < numLoops() && loop(k).depth() > depth) continue; 513 return k - 1; 514 } 515 516 /** 517 * Return the area of the polygon interior, i.e. the region on the left side 518 * of an odd number of loops. The return value is between 0 and 4*Pi. 519 */ 520 double getArea() const { 521 double area = 0; 522 for (int i = 0; i < numLoops(); ++i) { 523 area += loop(i).sign() * loop(i).getArea(); 524 } 525 return area; 526 } 527 528 /** 529 * Return the true centroid of the polygon multiplied by the area of the 530 * polygon (see s2centroids.h for details on centroids). The result is not 531 * unit length, so you may want to normalize it. Also note that in general, 532 * the centroid may not be contained by the polygon. 533 * 534 * We prescale by the polygon area for two reasons: (1) it is cheaper to 535 * compute this way, and (2) it makes it easier to compute the centroid of 536 * more complicated shapes (by splitting them into disjoint regions and 537 * adding their centroids). 538 */ 539 S2Point getCentroid() const { 540 S2Point centroid; 541 for (int i = 0; i < numLoops(); ++i) { 542 centroid += loop(i).sign() * loop(i).getCentroid(); 543 } 544 return centroid; 545 } 546 547 /** 548 * If all of the polygon's vertices happen to be the centers of S2Cells at 549 * some level, then return that level, otherwise return -1. See also 550 * InitToSnapped() and s2builderutil::S2CellIdSnapFunction. 551 * Returns -1 if the polygon has no vertices. 552 */ 553 int getSnapLevel() const { 554 import s2.s2coords : XYZtoFaceSiTi; 555 556 int snap_level = -1; 557 foreach (child; _loops) { 558 for (int j = 0; j < child.numVertices(); ++j) { 559 int face; 560 uint si, ti; 561 int level = XYZtoFaceSiTi(child.vertex(j), face, si, ti); 562 if (level < 0) return level; // Vertex is not a cell center. 563 if (level != snap_level) { 564 if (snap_level < 0) { 565 snap_level = level; // First vertex. 566 } else { 567 return -1; // Vertices at more than one cell level. 568 } 569 } 570 } 571 } 572 return snap_level; 573 } 574 575 /** 576 * Return the distance from the given point to the polygon interior. If the 577 * polygon is empty, return S1Angle::Infinity(). "x" should be unit length. 578 */ 579 S1Angle getDistance(in S2Point x) { 580 // Note that S2Polygon::Contains(S2Point) is slightly more efficient than 581 // the generic version used by S2ClosestEdgeQuery. 582 if (contains(x)) return S1Angle.zero(); 583 return getDistanceToBoundary(x); 584 } 585 586 /** 587 * Return the distance from the given point to the polygon boundary. If the 588 * polygon is empty or full, return S1Angle::Infinity() (since the polygon 589 * has no boundary). "x" should be unit length. 590 */ 591 S1Angle getDistanceToBoundary(in S2Point x) { 592 import s2.s2closest_edge_query; 593 594 auto options = new S2ClosestEdgeQuery.Options(); 595 options.setIncludeInteriors(false); 596 auto t = new S2ClosestEdgeQuery.PointTarget(x); 597 return new S2ClosestEdgeQuery(_index, options).getDistance(t).toS1Angle(); 598 } 599 600 static struct OverlapFractions { 601 double first; 602 double second; 603 } 604 605 /** 606 * Return the overlap fractions between two polygons, i.e. the ratios of the 607 * area of intersection to the area of each polygon. 608 */ 609 static OverlapFractions getOverlapFractions(S2Polygon a, S2Polygon b) { 610 auto intersection = new S2Polygon(); 611 intersection.initializeToIntersection(a, b); 612 double intersection_area = intersection.getArea(); 613 double a_area = a.getArea(); 614 double b_area = b.getArea(); 615 return OverlapFractions( 616 intersection_area >= a_area ? 1.0 : intersection_area / a_area, 617 intersection_area >= b_area ? 1.0 : intersection_area / b_area); 618 } 619 620 /** 621 * If the given point is contained by the polygon, return it. Otherwise 622 * return the closest point on the polygon boundary. If the polygon is 623 * empty, return the input argument. Note that the result may or may not be 624 * contained by the polygon. "x" should be unit length. 625 */ 626 S2Point project(in S2Point x) { 627 if (contains(x)) return x; 628 return projectToBoundary(x); 629 } 630 631 /** 632 * Return the closest point on the polygon boundary to the given point. If 633 * the polygon is empty or full, return the input argument (since the 634 * polygon has no boundary). "x" should be unit length. 635 */ 636 S2Point projectToBoundary(in S2Point x) { 637 import s2.s2closest_edge_query; 638 639 auto options = new S2ClosestEdgeQuery.Options(); 640 options.setIncludeInteriors(false); 641 auto q = new S2ClosestEdgeQuery(_index, options); 642 auto target = new S2ClosestEdgeQuery.PointTarget(x); 643 S2ClosestEdgeQuery.Result edge = q.findClosestEdge(target); 644 return q.project(x, edge); 645 } 646 647 /** 648 * Return true if this polygon contains the given other polygon, i.e. 649 * if polygon A contains all points contained by polygon B. 650 */ 651 bool contains(S2Polygon b) { 652 // It's worth checking bounding rectangles, since they are precomputed. 653 // Note that the first bound has been expanded to account for possible 654 // numerical errors in the second bound. 655 if (!_subregionBound.contains(b._bound)) { 656 // It is possible that A contains B even though Bound(A) does not contain 657 // Bound(B). This can only happen when polygon B has at least two outer 658 // shells and the union of the two bounds spans all longitudes. For 659 // example, suppose that B consists of two shells with a longitude gap 660 // between them, while A consists of one shell that surrounds both shells 661 // of B but goes the other way around the sphere (so that it does not 662 // intersect the longitude gap). 663 // 664 // For convenience we just check whether B has at least two loops rather 665 // than two outer shells. 666 if (b.numLoops() == 1 || !_bound.lng().unite(b._bound.lng()).isFull()) { 667 return false; 668 } 669 } 670 671 // The following case is not handled by S2BooleanOperation because it only 672 // determines whether the boundary of the result is empty (which does not 673 // distinguish between the full and empty polygons). 674 if (isEmpty() && b.isFull()) return false; 675 676 return S2BooleanOperation.contains(_index, b._index); 677 } 678 679 /** 680 * Returns true if this polgyon (A) approximately contains the given other 681 * polygon (B). This is true if it is possible to move the vertices of B 682 * no further than "tolerance" such that A contains the modified B. 683 * 684 * For example, the empty polygon will contain any polygon whose maximum 685 * width is no more than "tolerance". 686 */ 687 bool approxContains(S2Polygon b, S1Angle tolerance) { 688 auto difference = new S2Polygon(); 689 difference.initializeToApproxDifference(b, this, tolerance); 690 return difference.isEmpty(); 691 } 692 693 /** 694 * Return true if this polygon intersects the given other polygon, i.e. 695 * if there is a point that is contained by both polygons. 696 */ 697 bool intersects(S2Polygon b) { 698 // It's worth checking bounding rectangles, since they are precomputed. 699 if (!_bound.intersects(b._bound)) return false; 700 701 // The following case is not handled by S2BooleanOperation because it only 702 // determines whether the boundary of the result is empty (which does not 703 // distinguish between the full and empty polygons). 704 if (isFull() && b.isFull()) return true; 705 706 return S2BooleanOperation.intersects(_index, b._index); 707 } 708 709 /** 710 * Returns true if this polgyon (A) and the given polygon (B) are 711 * approximately disjoint. This is true if it is possible to ensure that A 712 * and B do not intersect by moving their vertices no further than 713 * "tolerance". This implies that in borderline cases where A and B overlap 714 * slightly, this method returns true (A and B are approximately disjoint). 715 * 716 * For example, any polygon is approximately disjoint from a polygon whose 717 * maximum width is no more than "tolerance". 718 */ 719 bool approxDisjoint(S2Polygon b, S1Angle tolerance) { 720 auto intersection = new S2Polygon(); 721 intersection.initializeToApproxIntersection(b, this, tolerance); 722 return intersection.isEmpty(); 723 } 724 725 /** 726 * Initialize this polygon to the intersection, union, difference (A - B), 727 * or symmetric difference (XOR) of the given two polygons. 728 * 729 * "snap_function" allows you to specify a minimum spacing between output 730 * vertices, and/or that the vertices should be snapped to a discrete set of 731 * points (e.g. S2CellId centers or E7 lat/lng coordinates). Any snap 732 * function can be used, including the IdentitySnapFunction with a 733 * snap_radius of zero (which preserves the input vertices exactly). 734 * 735 * The boundary of the output polygon before snapping is guaranteed to be 736 * accurate to within S2::kIntersectionError of the exact result. 737 * Snapping can move the boundary by an additional distance that depends on 738 * the snap function. Finally, any degenerate portions of the output 739 * polygon are automatically removed (i.e., regions that do not contain any 740 * points) since S2Polygon does not allow such regions. 741 * 742 * See S2Builder and s2builderutil for more details on snap functions. For 743 * example, you can snap to E7 coordinates by setting "snap_function" to 744 * s2builderutil::IntLatLngSnapFunction(7). 745 * 746 * The default snap function is the IdentitySnapFunction with a snap radius 747 * of S2::kIntersectionMergeRadius (equal to about 1.8e-15 radians 748 * or 11 nanometers on the Earth's surface). This means that vertices may 749 * be positioned arbitrarily, but vertices that are extremely close together 750 * can be merged together. The reason for a non-zero default snap radius is 751 * that it helps to eliminate narrow cracks and slivers when T-vertices are 752 * present. For example, adjacent S2Cells at different levels do not share 753 * exactly the same boundary, so there can be a narrow crack between them. 754 * If a polygon is intersected with those cells and the pieces are unioned 755 * together, the result would have a narrow crack unless the snap radius is 756 * set to a non-zero value. 757 * 758 * Note that if you want to encode the vertices in a lower-precision 759 * representation (such as S2CellIds or E7), it is much better to use a 760 * suitable SnapFunction rather than rounding the vertices yourself, because 761 * this will create self-intersections unless you ensure that the vertices 762 * and edges are sufficiently well-separated first. In particular you need 763 * to use a snap function whose min_edge_vertex_separation() is at least 764 * twice the maximum distance that a vertex can move when rounded. 765 */ 766 void initializeToIntersection(S2Polygon a, S2Polygon b) { 767 initializeToApproxIntersection(a, b, INTERSECTION_MERGE_RADIUS); 768 } 769 770 void initializeToIntersection( 771 S2Polygon a, S2Polygon b, S2Builder.SnapFunction snap_function) { 772 if (!a._bound.intersects(b._bound)) return; 773 initializeToOperation(S2BooleanOperation.OpType.INTERSECTION, snap_function, a, b); 774 775 // If the boundary is empty then there are two possible results: the empty 776 // polygon or the full polygon. Note that the (approximate) intersection of 777 // two non-full polygons may be full, because one or both polygons may have 778 // tiny cracks or holes that are eliminated by snapping. Similarly, the 779 // (approximate) intersection of two polygons that contain a common point 780 // may be empty, since the point might be contained by tiny loops that are 781 // snapped away. 782 // 783 // So instead we fall back to heuristics. First we compute the minimum and 784 // maximum intersection area based on the areas of the two input polygons. 785 // If only one of {0, 4*Pi} is possible then we return that result. If 786 // neither is possible (before snapping) then we return the one that is 787 // closest to being possible. (It never true that both are possible.) 788 if (numLoops() == 0) { 789 // We know that both polygons are non-empty due to the initial bounds 790 // check. By far the most common case is that the intersection is empty, 791 // so we want to make that case fast. The intersection area satisfies: 792 // 793 // max(0, A + B - 4*Pi) <= Intersection(A, B) <= min(A, B) 794 // 795 // where A, B can refer to a polygon or its area. Note that if either A 796 // or B is at most 2*Pi, the result must be "empty". We can use the 797 // bounding rectangle areas as upper bounds on the polygon areas. 798 if (a._bound.area() <= 2 * M_PI || b._bound.area() <= 2 * M_PI) return; 799 double a_area = a.getArea(); 800 double b_area = b.getArea(); 801 double min_area = max(0.0, a_area + b_area - 4 * M_PI); 802 double max_area = min(a_area, b_area); 803 if (min_area > 4 * M_PI - max_area) { 804 invert(); 805 } 806 } 807 } 808 809 void initializeToUnion(S2Polygon a, S2Polygon b) { 810 initializeToApproxUnion(a, b, INTERSECTION_MERGE_RADIUS); 811 } 812 813 void initializeToUnion(S2Polygon a, S2Polygon b, S2Builder.SnapFunction snap_function) { 814 initializeToOperation(S2BooleanOperation.OpType.UNION, snap_function, a, b); 815 if (numLoops() == 0) { 816 // See comments in InitToApproxIntersection(). In this case, the union 817 // area satisfies: 818 // 819 // max(A, B) <= Union(A, B) <= min(4*Pi, A + B) 820 // 821 // where A, B can refer to a polygon or its area. The most common case is 822 // that neither input polygon is empty, but the union is empty due to 823 // snapping. 824 if (a._bound.area() + b._bound.area() <= 2 * M_PI) return; 825 double a_area = a.getArea(); 826 double b_area = b.getArea(); 827 double min_area = max(a_area, b_area); 828 double max_area = min(4 * M_PI, a_area + b_area); 829 if (min_area > 4 * M_PI - max_area) { 830 invert(); 831 } 832 } 833 } 834 835 void initializeToDifference(S2Polygon a, S2Polygon b) { 836 initializeToApproxDifference(a, b, INTERSECTION_MERGE_RADIUS); 837 } 838 839 void initializeToDifference( 840 S2Polygon a, S2Polygon b, S2Builder.SnapFunction snap_function) { 841 initializeToOperation(S2BooleanOperation.OpType.DIFFERENCE, snap_function, a, b); 842 if (numLoops() == 0) { 843 // See comments in InitToApproxIntersection(). In this case, the 844 // difference area satisfies: 845 // 846 // max(0, A - B) <= Difference(A, B) <= min(A, 4*Pi - B) 847 // 848 // where A, B can refer to a polygon or its area. By far the most common 849 // case is that result is empty. 850 if (a._bound.area() <= 2 * M_PI || b._bound.area() >= 2 * M_PI) return; 851 double a_area = a.getArea(); 852 double b_area = b.getArea(); 853 double min_area = max(0.0, a_area - b_area); 854 double max_area = min(a_area, 4 * M_PI - b_area); 855 if (min_area > 4 * M_PI - max_area) { 856 invert(); 857 } 858 } 859 } 860 861 void initializeToSymmetricDifference(S2Polygon a, S2Polygon b) { 862 initializeToApproxSymmetricDifference(a, b, INTERSECTION_MERGE_RADIUS); 863 } 864 865 void initializeToSymmetricDifference( 866 S2Polygon a, S2Polygon b, S2Builder.SnapFunction snap_function) { 867 initializeToOperation(S2BooleanOperation.OpType.SYMMETRIC_DIFFERENCE, snap_function, a, b); 868 if (numLoops() == 0) { 869 // See comments in InitToApproxIntersection(). In this case, the 870 // difference area satisfies: 871 // 872 // |A - B| <= SymmetricDifference(A, B) <= 4*Pi - |4*Pi - (A + B)| 873 // 874 // where A, B can refer to a polygon or its area. By far the most common 875 // case is that result is empty. 876 if (a._bound.area() + b._bound.area() <= 2 * M_PI) return; 877 double a_area = a.getArea(); 878 double b_area = b.getArea(); 879 double min_area = fabs(a_area - b_area); 880 double max_area = 4 * M_PI - fabs(4 * M_PI - (a_area + b_area)); 881 // If both input polygons have area 2*Pi, the result could be either empty 882 // or full. We explicitly want to choose "empty" in this case since it is 883 // much more likely that the user is computing the difference between two 884 // nearly identical polygons. Hence the bias below. 885 enum double kBiasTowardsEmpty = 1e-14; 886 if (min_area - kBiasTowardsEmpty > 4 * M_PI - max_area) { 887 invert(); 888 } 889 } 890 } 891 892 // Convenience functions that use the IdentitySnapFunction with the given 893 // snap radius. TODO(ericv): Consider deprecating these and require the 894 // snap function to be specified explcitly? 895 void initializeToApproxIntersection(S2Polygon a, S2Polygon b, S1Angle snap_radius) { 896 initializeToIntersection(a, b, new IdentitySnapFunction(snap_radius)); 897 } 898 void initializeToApproxUnion(S2Polygon a, S2Polygon b, S1Angle snap_radius) { 899 initializeToUnion(a, b, new IdentitySnapFunction(snap_radius)); 900 } 901 void initializeToApproxDifference(S2Polygon a, S2Polygon b, S1Angle snap_radius) { 902 initializeToDifference(a, b, new IdentitySnapFunction(snap_radius)); 903 } 904 void initializeToApproxSymmetricDifference(S2Polygon a, S2Polygon b, S1Angle snap_radius) { 905 initializeToSymmetricDifference(a, b, new IdentitySnapFunction(snap_radius)); 906 } 907 908 /** 909 * Snaps the vertices of the given polygon using the given SnapFunction 910 * (e.g., s2builderutil::IntLatLngSnapFunction(6) snaps to E6 coordinates). 911 * This can change the polygon topology (merging loops, for example), but 912 * the resulting polygon is guaranteed to be valid, and no vertex will move 913 * by more than snap_function.snap_radius(). See S2Builder for other 914 * guarantees (e.g., minimum edge-vertex separation). 915 * 916 * Note that this method is a thin wrapper over S2Builder, so if you are 917 * starting with data that is not in S2Polygon format (e.g., integer E7 918 * coordinates) then it is faster to just use S2Builder directly. 919 */ 920 void initializeToSnapped(in S2Polygon a, in S2Builder.SnapFunction snap_function) { 921 auto options = new S2Builder.Options(snap_function); 922 options.setSimplifyEdgeChains(true); 923 auto builder = new S2Builder(options); 924 initializeFromBuilder(a, builder); 925 } 926 927 /** 928 * Convenience function that snaps the vertices to S2CellId centers at the 929 * given level (default level 30, which has S2CellId centers spaced about 1 930 * centimeter apart). Polygons can be efficiently encoded by Encode() after 931 * they have been snapped. 932 */ 933 void initializeToSnapped(in S2Polygon a, int snap_level = S2CellId.MAX_LEVEL) { 934 auto builder = new S2Builder(new S2Builder.Options(new S2CellIdSnapFunction(snap_level))); 935 initializeFromBuilder(a, builder); 936 } 937 938 /** 939 * Snaps the input polygon according to the given "snap_function" and 940 * reduces the number of vertices if possible, while ensuring that no vertex 941 * moves further than snap_function.snap_radius(). 942 * 943 * Simplification works by replacing nearly straight chains of short edges 944 * with longer edges, in a way that preserves the topology of the input 945 * polygon up to the creation of degeneracies. This means that loops or 946 * portions of loops may become degenerate, in which case they are removed. 947 * For example, if there is a very small island in the original polygon, it 948 * may disappear completely. (Even if there are dense islands, they could 949 * all be removed rather than being replaced by a larger simplified island 950 * if more area is covered by water than land.) 951 */ 952 void initializeToSimplified(in S2Polygon a, S2Builder.SnapFunction snap_function) { 953 auto options = new S2Builder.Options(snap_function); 954 options.setSimplifyEdgeChains(true); 955 auto builder = new S2Builder(options); 956 initializeFromBuilder(a, builder); 957 } 958 959 /** 960 * Like InitToSimplified, except that any vertices or edges on the boundary 961 * of the given S2Cell are preserved if possible. This method requires that 962 * the polygon has already been clipped so that it does not extend outside 963 * the cell by more than "boundary_tolerance". In other words, it operates 964 * on polygons that have already been intersected with a cell. 965 * 966 * Typically this method is used in geometry-processing pipelines that 967 * intersect polygons with a collection of S2Cells and then process those 968 * cells in parallel, where each cell generates some geometry that needs to 969 * be simplified. In contrast, if you just need to simplify the *input* 970 * geometry then it is easier and faster to do the simplification before 971 * computing the intersection with any S2Cells. 972 * 973 * "boundary_tolerance" specifies how close a vertex must be to the cell 974 * boundary to be kept. The default tolerance is large enough to handle any 975 * reasonable way of interpolating points along the cell boundary, such as 976 * S2::GetIntersection(), S2::Interpolate(), or direct (u,v) 977 * interpolation using S2::FaceUVtoXYZ(). However, if the vertices have 978 * been snapped to a lower-precision representation (e.g., S2CellId centers 979 * or E7 coordinates) then you will need to set this tolerance explicitly. 980 * For example, if the vertices were snapped to E7 coordinates then 981 * "boundary_tolerance" should be set to 982 * 983 * s2builderutil::IntLatLngSnapFunction::MinSnapRadiusForExponent(7) 984 * 985 * Degenerate portions of loops are always removed, so if a vertex on the 986 * cell boundary belongs only to degenerate regions then it will not be 987 * kept. For example, if the input polygon is a narrow strip of width less 988 * than "snap_radius" along one side of the cell, then the entire loop may 989 * become degenerate and be removed. 990 * 991 * REQUIRES: all vertices of "a" are within "boundary_tolerance" of "cell". 992 */ 993 void initializeToSimplifiedInCell( 994 in S2Polygon a, in S2Cell cell, S1Angle snap_radius, 995 S1Angle boundary_tolerance = S1Angle.fromRadians(1e-15)) { 996 // The polygon to be simplified consists of "boundary edges" that follow the 997 // cell boundary and "interior edges" that do not. We want to simplify the 998 // interior edges while leaving the boundary edges unchanged. It's not 999 // sufficient to call S2Builder::ForceVertex() on all boundary vertices. 1000 // For example, suppose the polygon includes a triangle ABC where all three 1001 // vertices are on the cell boundary and B is a cell corner. Then if 1002 // interior edge AC snaps to vertex B, this loop would become degenerate and 1003 // be removed. Similarly, we don't want boundary edges to snap to interior 1004 // vertices, since this also would cause portions of the polygon along the 1005 // boundary to be removed. 1006 // 1007 // Instead we use a two-pass algorithm. In the first pass, we simplify 1008 // *only* the interior edges, using ForceVertex() to ensure that any edge 1009 // endpoints on the cell boundary do not move. In the second pass, we add 1010 // the boundary edges (which are guaranteed to still form loops with the 1011 // interior edges) and build the output polygon. 1012 // 1013 // Note that in theory, simplifying the interior edges could create an 1014 // intersection with one of the boundary edges, since if two interior edges 1015 // intersect very near the boundary then the intersection point could be 1016 // slightly outside the cell (by at most S2::kIntersectionError). 1017 // This is the *only* way that a self-intersection can be created, and it is 1018 // expected to be extremely rare. Nevertheless we use a small snap radius 1019 // in the second pass in order to eliminate any such self-intersections. 1020 // 1021 // We also want to preserve the cyclic vertex order of loops, so that the 1022 // original polygon can be reconstructed when no simplification is possible 1023 // (i.e., idempotency). In order to do this, we group the input edges into 1024 // a sequence of polylines. Each polyline contains only one type of edge 1025 // (interior or boundary). We use S2Builder to simplify the interior 1026 // polylines, while the boundary polylines are passed through unchanged. 1027 // Each interior polyline is in its own S2Builder layer in order to keep the 1028 // edges in sequence. This lets us ensure that in the second pass, the 1029 // edges are added in their original order so that S2PolygonLayer can 1030 // reconstruct the original loops. 1031 1032 // We want an upper bound on how much "u" or "v" can change when a point on 1033 // the boundary of the S2Cell is moved away by up to "boundary_tolerance". 1034 // Inverting this, instead we could compute a lower bound on how far a point 1035 // can move away from an S2Cell edge when "u" or "v" is changed by a given 1036 // amount. The latter quantity is simply (S2::kMinWidth.deriv() / 2) 1037 // under the S2_LINEAR_PROJECTION model, where we divide by 2 because we 1038 // want the bound in terms of (u = 2 * s - 1) rather than "s" itself. 1039 // Consulting s2metrics.cc, this value is sqrt(2/3)/2 = sqrt(1/6). 1040 // Going back to the original problem, this gives: 1041 double boundary_tolerance_uv = sqrt(6.0) * boundary_tolerance.radians(); 1042 1043 // The first pass yields a collection of simplified polylines that preserve 1044 // the original cyclic vertex order. 1045 auto polylines = simplifyEdgesInCell(a, cell, boundary_tolerance_uv, snap_radius); 1046 1047 // The second pass eliminates any intersections between interior edges and 1048 // boundary edges, and then assembles the edges into a polygon. 1049 auto options = new S2Builder.Options(new IdentitySnapFunction(INTERSECTION_ERROR)); 1050 options.setIdempotent(false); // Force snapping up to the given radius 1051 auto builder = new S2Builder(options); 1052 builder.startLayer(new S2PolygonLayer(this)); 1053 foreach (polyline; polylines) { 1054 builder.addPolyline(polyline); 1055 } 1056 S2Error error; 1057 if (!builder.build(error)) { 1058 logger.logFatal("Could not build polygon: ", error); 1059 return; 1060 } 1061 // If there are no loops, check whether the result should be the full 1062 // polygon rather than the empty one. (See InitToApproxIntersection.) 1063 if (numLoops() == 0) { 1064 if (a._bound.area() > 2 * M_PI && a.getArea() > 2 * M_PI) invert(); 1065 } 1066 } 1067 1068 /// Initialize this polygon to the complement of the given polygon. 1069 void initializeToComplement(in S2Polygon a) { 1070 copy(a); 1071 invert(); 1072 } 1073 1074 /// Invert the polygon (replace it by its complement). 1075 void invert() { 1076 // Inverting any one loop will invert the polygon. The best loop to invert 1077 // is the one whose area is largest, since this yields the smallest area 1078 // after inversion. The loop with the largest area is always at depth 0. 1079 // The descendents of this loop all have their depth reduced by 1, while the 1080 // former siblings of this loop all have their depth increased by 1. 1081 1082 // The empty and full polygons are handled specially. 1083 if (isEmpty()) { 1084 _loops ~= new S2Loop(S2Loop.full()); 1085 } else if (isFull()) { 1086 clearLoops(); 1087 } else { 1088 // Find the loop whose area is largest (i.e., whose turning angle is 1089 // smallest), minimizing calls to GetTurningAngle(). In particular, for 1090 // polygons with a single shell at level 0 there is not need to call 1091 // GetTurningAngle() at all. (This method is relatively expensive.) 1092 int best = 0; 1093 const double kNone = 10.0; // Flag that means "not computed yet" 1094 double best_angle = kNone; 1095 for (int i = 1; i < numLoops(); ++i) { 1096 if (loop(i).depth() == 0) { 1097 // We defer computing the turning angle of loop 0 until we discover 1098 // that the polygon has another top-level shell. 1099 if (best_angle == kNone) best_angle = loop(best).getTurningAngle(); 1100 double angle = loop(i).getTurningAngle(); 1101 // We break ties deterministically in order to avoid having the output 1102 // depend on the input order of the loops. 1103 if (angle < best_angle || 1104 (angle == best_angle && compareLoops(loop(i), loop(best)) < 0)) { 1105 best = i; 1106 best_angle = angle; 1107 } 1108 } 1109 } 1110 // Build the new loops vector, starting with the inverted loop. 1111 loop(best).invert(); 1112 S2Loop[] new_loops; 1113 new_loops.reserve(numLoops()); 1114 // Add the former siblings of this loop as descendants. 1115 int last_best = getLastDescendant(best); 1116 new_loops ~= _loops[best]; // TODO: Remove from _loops? 1117 for (int i = 0; i < numLoops(); ++i) { 1118 if (i < best || i > last_best) { 1119 loop(i).setDepth(loop(i).depth() + 1); 1120 new_loops ~= _loops[i]; // TODO: Remove from _loops? 1121 } 1122 } 1123 // Add the former children of this loop as siblings. 1124 for (int i = 0; i < numLoops(); ++i) { 1125 if (i > best && i <= last_best) { 1126 loop(i).setDepth(loop(i).depth() - 1); 1127 new_loops ~= _loops[i]; // TODO: Remove from _loops? 1128 } 1129 } 1130 _loops.swap(new_loops); 1131 enforce(new_loops.length == numLoops()); 1132 } 1133 clearIndex(); 1134 initializeLoopProperties(); 1135 } 1136 1137 /** 1138 * Return true if this polygon contains the given polyline. This method 1139 * returns an exact result, according to the following model: 1140 * 1141 * - All edges are geodesics (of course). 1142 * 1143 * - Vertices are ignored for the purposes of defining containment. 1144 * (This is because polygons often do not contain their vertices, in 1145 * order to that when a set of polygons tiles the sphere then every point 1146 * is contained by exactly one polygon.) 1147 * 1148 * - Points that lie exactly on geodesic edges are resolved using symbolic 1149 * perturbations (i.e., they are considered to be infinitesmally offset 1150 * from the edge). 1151 * 1152 * - If the polygon and polyline share an edge, it is handled as follows. 1153 * First, the polygon edges are oriented so that the interior is always 1154 * on the left. Then the shared polyline edge is contained if and only 1155 * if it is in the same direction as the corresponding polygon edge. 1156 * (This model ensures that when a polyline is intersected with a polygon 1157 * and its complement, the edge only appears in one of the two results.) 1158 * 1159 * TODO(ericv): Update the implementation to correspond to the model above. 1160 */ 1161 bool contains(in S2Polyline b) { 1162 return approxContains(b, INTERSECTION_MERGE_RADIUS); 1163 } 1164 1165 /** 1166 * Returns true if this polgyon approximately contains the given polyline 1167 * This is true if it is possible to move the polyline vertices no further 1168 * than "tolerance" such that the polyline is now contained. 1169 */ 1170 bool approxContains(in S2Polyline b, S1Angle tolerance) { 1171 auto difference = approxSubtractFromPolyline(b, tolerance); 1172 return difference.empty(); 1173 } 1174 1175 /** 1176 * Return true if this polygon intersects the given polyline. This method 1177 * returns an exact result; see Contains(S2Polyline) for details. 1178 */ 1179 bool intersects(in S2Polyline b) { 1180 return !approxDisjoint(b, INTERSECTION_MERGE_RADIUS); 1181 } 1182 1183 /** 1184 * Returns true if this polgyon is approximately disjoint from the given 1185 * polyline. This is true if it is possible to avoid intersection by moving 1186 * their vertices no further than "tolerance". 1187 * 1188 * This implies that in borderline cases where there is a small overlap, 1189 * this method returns true (i.e., they are approximately disjoint). 1190 */ 1191 bool approxDisjoint(const S2Polyline b, S1Angle tolerance) { 1192 auto intersection = approxIntersectWithPolyline(b, tolerance); 1193 return intersection.empty(); 1194 } 1195 1196 /** 1197 * Intersect this polygon with the polyline "in" and return the resulting 1198 * zero or more polylines. The polylines are returned in the order they 1199 * would be encountered by traversing "in" from beginning to end. 1200 * Note that the output may include polylines with only one vertex, 1201 * but there will not be any zero-vertex polylines. 1202 * 1203 * This is equivalent to calling ApproxIntersectWithPolyline() with the 1204 * "snap_radius" set to S2::kIntersectionMergeRadius. 1205 */ 1206 S2Polyline[] intersectWithPolyline(in S2Polyline a) { 1207 return approxIntersectWithPolyline(a, INTERSECTION_MERGE_RADIUS); 1208 } 1209 1210 /** 1211 * Similar to IntersectWithPolyline(), except that vertices will be 1212 * dropped as necessary to ensure that all adjacent vertices in the 1213 * sequence obtained by concatenating the output polylines will be 1214 * farther than "snap_radius" apart. Note that this can change 1215 * the number of output polylines and/or yield single-vertex polylines. 1216 */ 1217 S2Polyline[] approxIntersectWithPolyline(in S2Polyline a, S1Angle snap_radius) { 1218 return intersectWithPolyline(a, new IdentitySnapFunction(snap_radius)); 1219 } 1220 1221 // TODO(ericv): Update documentation. 1222 S2Polyline[] intersectWithPolyline( 1223 in S2Polyline a, S2Builder.SnapFunction snap_function) { 1224 return operationWithPolyline(S2BooleanOperation.OpType.INTERSECTION, snap_function, a); 1225 } 1226 1227 /** 1228 * Same as IntersectWithPolyline, but subtracts this polygon from 1229 * the given polyline. 1230 */ 1231 S2Polyline[] subtractFromPolyline(in S2Polyline a) { 1232 return approxSubtractFromPolyline(a, INTERSECTION_MERGE_RADIUS); 1233 } 1234 1235 /** 1236 * Same as ApproxIntersectWithPolyline, but subtracts this polygon 1237 * from the given polyline. 1238 */ 1239 S2Polyline[] approxSubtractFromPolyline(in S2Polyline a, S1Angle snap_radius) { 1240 return subtractFromPolyline(a, new IdentitySnapFunction(snap_radius)); 1241 } 1242 1243 S2Polyline[] subtractFromPolyline(in S2Polyline a, S2Builder.SnapFunction snap_function) { 1244 return operationWithPolyline(S2BooleanOperation.OpType.DIFFERENCE, snap_function, a); 1245 } 1246 1247 /// Return a polygon which is the union of the given polygons. 1248 static S2Polygon destructiveUnion(S2Polygon[] polygons) { 1249 return destructiveApproxUnion(polygons, INTERSECTION_MERGE_RADIUS); 1250 } 1251 1252 static S2Polygon destructiveApproxUnion(S2Polygon[] polygons, S1Angle snap_radius) { 1253 // Effectively create a priority queue of polygons in order of number of 1254 // vertices. Repeatedly union the two smallest polygons and add the result 1255 // to the queue until we have a single polygon to return. 1256 alias QueueType = BTreeMap!(int, S2Polygon); 1257 auto queue = new QueueType(); // Map from # of vertices to polygon. 1258 foreach (polygon; polygons) 1259 queue.insert(polygon.numVertices(), polygon); 1260 1261 while (queue.length > 1) { 1262 // Pop two simplest polygons from queue. 1263 QueueType.Iterator smallest_it = queue.begin(); 1264 int a_size = smallest_it.getValue().key; 1265 auto a_polygon = smallest_it.getValue().value; 1266 queue.remove(smallest_it.getValue().key); 1267 smallest_it = queue.begin(); 1268 int b_size = smallest_it.getValue().key; 1269 auto b_polygon = smallest_it.getValue().value; 1270 queue.remove(smallest_it.getValue().key); 1271 1272 // Union and add result back to queue. 1273 auto union_polygon = new S2Polygon(); 1274 union_polygon.initializeToApproxUnion(a_polygon, b_polygon, snap_radius); 1275 queue.insert(a_size + b_size, union_polygon); 1276 // We assume that the number of vertices in the union polygon is the 1277 // sum of the number of vertices in the original polygons, which is not 1278 // always true, but will almost always be a decent approximation, and 1279 // faster than recomputing. 1280 } 1281 1282 if (queue.empty()) 1283 return new S2Polygon(); 1284 else 1285 return queue.begin().getValue().value; 1286 } 1287 1288 /** 1289 * Initialize this polygon to the outline of the given cell union. 1290 * In principle this polygon should exactly contain the cell union and 1291 * this polygon's inverse should not intersect the cell union, but rounding 1292 * issues may cause this not to be the case. 1293 */ 1294 void initializeToCellUnionBorder(in S2CellUnion cells) { 1295 // We use S2Builder to compute the union. Due to rounding errors, we can't 1296 // compute an exact union - when a small cell is adjacent to a larger cell, 1297 // the shared edges can fail to line up exactly. Two cell edges cannot come 1298 // closer then kMinWidth, so if we have S2Builder snap edges within half 1299 // that distance, then we should always merge shared edges without merging 1300 // different edges. 1301 double snap_radius = 0.5 * MIN_WIDTH.getValue(S2CellId.MAX_LEVEL); 1302 auto builder = new S2Builder(new S2Builder.Options( 1303 new IdentitySnapFunction(S1Angle.fromRadians(snap_radius)))); 1304 builder.startLayer(new S2PolygonLayer(this)); 1305 foreach (S2CellId id; cells.cellIds) { 1306 builder.addLoop(new S2Loop(new S2Cell(id))); 1307 } 1308 S2Error error; 1309 if (!builder.build(error)) { 1310 logger.logFatal("InitToCellUnionBorder failed: ", error); 1311 } 1312 1313 // If there are no loops, check whether the result should be the full 1314 // polygon rather than the empty one. There are only two ways that this can 1315 // happen: either the cell union is empty, or it consists of all six faces. 1316 if (numLoops() == 0) { 1317 if (cells.empty()) return; 1318 enforce(6uL << (2 * S2CellId.MAX_LEVEL) == cells.leafCellsCovered()); 1319 invert(); 1320 } 1321 } 1322 1323 /** 1324 * Return true if every loop of this polygon shares at most one vertex with 1325 * its parent loop. Every polygon has a unique normalized form. A polygon 1326 * can be normalized by passing it through S2Builder (with no snapping) in 1327 * order to reconstruct the polygon from its edges. 1328 * 1329 * Generally there is no reason to convert polygons to normalized form. It 1330 * is mainly useful for testing in order to compare whether two polygons 1331 * have exactly the same interior, even when they have a different loop 1332 * structure. For example, a diamond nested within a square (touching at 1333 * four points) could be represented as a square with a diamond-shaped hole, 1334 * or as four triangles. Methods such as BoundaryApproxEquals() will report 1335 * these polygons as being different (because they have different 1336 * boundaries) even though they contain the same points. However if they 1337 * are both converted to normalized form (the "four triangles" version) then 1338 * they can be compared more easily. 1339 * 1340 * Also see ApproxEquals(), which can determine whether two polygons contain 1341 * approximately the same set of points without any need for normalization. 1342 */ 1343 bool isNormalized() const { 1344 import std.algorithm : count; 1345 1346 // TODO(ericv): The condition tested here is insufficient. The correct 1347 // condition is that each *connected component* of child loops can share at 1348 // most one vertex with their parent loop. Example: suppose loop A has 1349 // children B, C, D, and the following pairs are connected: AB, BC, CD, DA. 1350 // Then the polygon is not normalized. 1351 auto vertices = new RedBlackTree!S2Point(); 1352 Rebindable!(const(S2Loop)) last_parent = null; 1353 for (int i = 0; i < numLoops(); ++i) { 1354 const(S2Loop) child = loop(i); 1355 if (child.depth() == 0) continue; 1356 Rebindable!(const(S2Loop)) parent = loop(getParent(i)); 1357 if (parent != last_parent) { 1358 vertices.clear(); 1359 for (int j = 0; j < parent.numVertices(); ++j) { 1360 vertices.insert(parent.vertex(j)); 1361 } 1362 last_parent = parent; 1363 } 1364 int cnt = 0; 1365 for (int j = 0; j < child.numVertices(); ++j) { 1366 if (count(vertices.equalRange(child.vertex(j))) > 0) ++cnt; 1367 } 1368 if (cnt > 1) return false; 1369 } 1370 return true; 1371 } 1372 1373 /** 1374 * Return true if two polygons have exactly the same loops. The loops must 1375 * appear in the same order, and corresponding loops must have the same 1376 * linear vertex ordering (i.e., cyclic rotations are not allowed). 1377 */ 1378 override 1379 bool opEquals(in Object o) const { 1380 S2Polygon b = cast(S2Polygon) o; 1381 if (b is null) return false; 1382 if (numLoops() != b.numLoops()) return false; 1383 for (int i = 0; i < numLoops(); ++i) { 1384 const S2Loop a_loop = loop(i); 1385 const S2Loop b_loop = b.loop(i); 1386 if ((b_loop.depth() != a_loop.depth()) || !b_loop.equals(a_loop)) { 1387 return false; 1388 } 1389 } 1390 return true; 1391 } 1392 1393 /** 1394 * Return true if two polygons are approximately equal to within the given 1395 * tolerance. This is true if it is possible to move the vertices of the 1396 * two polygons so that they contain the same set of points. 1397 * 1398 * Note that according to this model, small regions less than "tolerance" in 1399 * width do not need to be considered, since these regions can be collapsed 1400 * into degenerate loops (which contain no points) by moving their vertices. 1401 * 1402 * This model is not as strict as using the Hausdorff distance would be, and 1403 * it is also not as strict as BoundaryNear (defined below). However, it is 1404 * a good choice for comparing polygons that have been snapped, simplified, 1405 * unioned, etc, since these operations use a model similar to this one 1406 * (i.e., degenerate loops or portions of loops are automatically removed). 1407 */ 1408 bool approxEquals(S2Polygon b, S1Angle tolerance) { 1409 // TODO(ericv): This can be implemented more cheaply with S2Builder, by 1410 // simply adding all the edges from one polygon, adding the reversed edge 1411 // from the other polygon, and turning on the options to split edges and 1412 // discard sibling pairs. Then the polygons are approximately equal if the 1413 // output graph has no edges. 1414 auto symmetric_difference = new S2Polygon(); 1415 symmetric_difference.initializeToApproxSymmetricDifference(b, this, tolerance); 1416 return symmetric_difference.isEmpty(); 1417 } 1418 1419 /** 1420 * Returns true if two polygons have the same boundary. More precisely, 1421 * this method requires that both polygons have loops with the same cyclic 1422 * vertex order and the same nesting hierarchy. (This implies that vertices 1423 * may be cyclically rotated between corresponding loops, and the loop 1424 * ordering may be different between the two polygons as long as the nesting 1425 * hierarchy is the same.) 1426 */ 1427 bool boundaryEquals(in S2Polygon b) const { 1428 if (numLoops() != b.numLoops()) return false; 1429 1430 for (int i = 0; i < numLoops(); ++i) { 1431 const S2Loop a_loop = loop(i); 1432 bool success = false; 1433 for (int j = 0; j < numLoops(); ++j) { 1434 const S2Loop b_loop = b.loop(j); 1435 if (b_loop.depth() == a_loop.depth() && b_loop.boundaryEquals(a_loop)) { 1436 success = true; 1437 break; 1438 } 1439 } 1440 if (!success) return false; 1441 } 1442 return true; 1443 } 1444 1445 /** 1446 * Return true if two polygons have the same boundary except for vertex 1447 * perturbations. Both polygons must have loops with the same cyclic vertex 1448 * order and the same nesting hierarchy, but the vertex locations are 1449 * allowed to differ by up to "max_error". 1450 */ 1451 bool boundaryApproxEquals(in S2Polygon b, S1Angle max_error = S1Angle.fromRadians(1e-15)) const { 1452 if (numLoops() != b.numLoops()) return false; 1453 1454 // For now, we assume that there is at most one candidate match for each 1455 // loop. (So far this method is just used for testing.) 1456 1457 for (int i = 0; i < numLoops(); ++i) { 1458 const S2Loop a_loop = loop(i); 1459 bool success = false; 1460 for (int j = 0; j < numLoops(); ++j) { 1461 const S2Loop b_loop = b.loop(j); 1462 if (b_loop.depth() == a_loop.depth() && b_loop.boundaryApproxEquals(a_loop, max_error)) { 1463 success = true; 1464 break; 1465 } 1466 } 1467 if (!success) return false; 1468 } 1469 return true; 1470 } 1471 1472 /** 1473 * Return true if two polygons have boundaries that are within "max_error" 1474 * of each other along their entire lengths. More precisely, there must be 1475 * a bijection between the two sets of loops such that for each pair of 1476 * loops, "a_loop->BoundaryNear(b_loop)" is true. 1477 */ 1478 bool boundaryNear(in S2Polygon b, S1Angle max_error = S1Angle.fromRadians(1e-15)) const { 1479 if (numLoops() != b.numLoops()) return false; 1480 1481 // For now, we assume that there is at most one candidate match for each 1482 // loop. (So far this method is just used for testing.) 1483 1484 for (int i = 0; i < numLoops(); ++i) { 1485 const S2Loop a_loop = loop(i); 1486 bool success = false; 1487 for (int j = 0; j < numLoops(); ++j) { 1488 const S2Loop b_loop = b.loop(j); 1489 if (b_loop.depth() == a_loop.depth() && b_loop.boundaryNear(a_loop, max_error)) { 1490 success = true; 1491 break; 1492 } 1493 } 1494 if (!success) return false; 1495 } 1496 return true; 1497 } 1498 1499 // TODO: Fix this calculation, it is currently inaccurate. 1500 /// Returns the total number of bytes used by the polygon. 1501 size_t spaceUsed() const { 1502 size_t size = this.sizeof; 1503 for (int i = 0; i < numLoops(); ++i) { 1504 size += loop(i).spaceUsed(); 1505 } 1506 size += _index.spaceUsed() - _index.sizeof; 1507 return size; 1508 } 1509 1510 //////////////////////////////////////////////////////////////////////// 1511 // S2Region interface (see s2region.h for details): 1512 1513 /** 1514 * GetRectBound() returns essentially tight results, while GetCapBound() 1515 * might have a lot of extra padding. Both bounds are conservative in that 1516 * if the loop contains a point P, then the bound contains P also. 1517 */ 1518 override 1519 S2Polygon clone() const { 1520 S2Polygon result = new S2Polygon(); 1521 result.copy(this); 1522 return result; 1523 } 1524 1525 /// Cap surrounding rect bound. 1526 override 1527 S2Cap getCapBound() const { 1528 return _bound.getCapBound(); 1529 } 1530 1531 override 1532 S2LatLngRect getRectBound() const { 1533 return _bound.clone(); 1534 } 1535 1536 override 1537 void getCellUnionBound(out S2CellId[] cell_ids) { 1538 return makeS2ShapeIndexRegion(_index).getCellUnionBound(cell_ids); 1539 } 1540 1541 override 1542 bool contains(in S2Cell target) { 1543 return makeS2ShapeIndexRegion(_index).contains(target); 1544 } 1545 1546 override 1547 bool mayIntersect(in S2Cell target) { 1548 return makeS2ShapeIndexRegion(_index).mayIntersect(target); 1549 } 1550 1551 /// The point 'p' does not need to be normalized. 1552 override 1553 bool contains(in S2Point p) { 1554 // NOTE(ericv): A bounds check slows down this function by about 50%. It is 1555 // worthwhile only when it might allow us to delay building the index. 1556 if (!_index.isFresh() && !_bound.contains(p)) return false; 1557 1558 // For small polygons it is faster to just check all the crossings. 1559 // Otherwise we keep track of the number of calls to Contains() and only 1560 // build the index once enough calls have been made so that we think it is 1561 // worth the effort. See S2Loop::Contains(S2Point) for detailed comments. 1562 enum int kMaxBruteForceVertices = 32; 1563 enum int kMaxUnindexedContainsCalls = 20; 1564 if (numVertices() <= kMaxBruteForceVertices 1565 || !_index.isFresh() && atomicOp!"+="(_unindexedContainsCalls, 1) != kMaxUnindexedContainsCalls) { 1566 bool inside = false; 1567 for (int i = 0; i < numLoops(); ++i) { 1568 // Use brute force to avoid building the loop's S2ShapeIndex. 1569 inside ^= loop(i).bruteForceContains(p); 1570 } 1571 return inside; 1572 } 1573 // Otherwise we look up the S2ShapeIndex cell containing this point. 1574 return makeS2ContainsPointQuery(_index).contains(p); 1575 } 1576 1577 /** 1578 * Appends a serialized representation of the S2Polygon to "encoder". 1579 * 1580 * The encoding uses about 4 bytes per vertex for typical polygons in 1581 * Google's geographic repository, assuming that most vertices have been 1582 * snapped to the centers of S2Cells at some fixed level (typically using 1583 * InitToSnapped). The remaining vertices are stored using 24 bytes. 1584 * Decoding a polygon encoded this way always returns the original polygon, 1585 * without any loss of precision. 1586 * 1587 * The snap level is chosen to be the one that has the most vertices snapped 1588 * to S2Cells at that level. If most vertices need 24 bytes, then all 1589 * vertices are encoded this way (this method automatically chooses the 1590 * encoding that has the best chance of giving the smaller output size). 1591 */ 1592 void encode(ORangeT)(Encoder!ORangeT encoder) const { 1593 // TODO: Add after encodeCompressed is implemented. 1594 //if (num_vertices_ == 0) { 1595 // EncodeCompressed(encoder, nullptr, S2::kMaxCellLevel); 1596 // return; 1597 //} 1598 1599 // Converts all the polygon vertices to S2XYZFaceSiTi format. 1600 auto all_vertices = new S2XYZFaceSiTi[numVertices()]; 1601 size_t current_loop_index = 0; 1602 foreach (loop; _loops) { 1603 loop.getXYZFaceSiTiVertices(all_vertices, current_loop_index); 1604 current_loop_index += loop.numVertices(); 1605 } 1606 // Computes a histogram of the cell levels at which the vertices are snapped. 1607 // cell_level is -1 for unsnapped, or 0 through kMaxCellLevel if snapped, 1608 // so we add one to it to get a non-negative index. (histogram[0] is the 1609 // number of unsnapped vertices, histogram[i] the number of vertices 1610 // snapped at level i-1). 1611 int[MAX_CELL_LEVEL + 2] histogram; 1612 foreach (v; all_vertices) { 1613 histogram[v.cellLevel + 1] += 1; 1614 } 1615 // Compute the level at which most of the vertices are snapped. 1616 // If multiple levels have the same maximum number of vertices 1617 // snapped to it, the first one (lowest level number / largest 1618 // area / smallest encoding length) will be chosen, so this 1619 // is desired. Start with histogram[1] since histogram[0] is 1620 // the number of unsnapped vertices, which we don't care about. 1621 const max_index = maxIndex(histogram[1..$]); 1622 // snap_level will be at position histogram[snap_level + 1], see above. 1623 const int snap_level = cast(int) max_index - 1; 1624 const int num_snapped = histogram[max_index + 1]; 1625 // Choose an encoding format based on the number of unsnapped vertices and a 1626 // rough estimate of the encoded sizes. 1627 1628 // The compressed encoding requires approximately 4 bytes per vertex plus 1629 // "exact_point_size" for each unsnapped vertex (encoded as an S2Point plus 1630 // the index at which it is located). 1631 int exact_point_size = S2Point.sizeof + 2; 1632 int num_unsnapped = numVertices() - num_snapped; 1633 int compressed_size = 4 * numVertices() + exact_point_size * num_unsnapped; 1634 int lossless_size = cast(int) S2Point.sizeof * numVertices(); 1635 1636 // TODO: Add after encodeCompressed is implemented. 1637 //if (compressed_size < lossless_size) { 1638 // EncodeCompressed(encoder, all_vertices.data(), snap_level); 1639 //} else { 1640 encodeLossless(encoder); 1641 //} 1642 } 1643 1644 /// Decodes a polygon encoded with Encode(). Returns true on success. 1645 bool decode(IRangeT)(Decoder!IRangeT decoder) { 1646 if (decoder.avail() < ubyte.sizeof) return false; 1647 ubyte versionNum = decoder.get8(); 1648 switch (versionNum) { 1649 case CURRENT_LOSSLESS_ENCODING_VERSION_NUMBER: 1650 return decodeLossless(decoder, false); 1651 case CURRENT_COMPRESSED_ENCODING_VERSION_NUMBER: 1652 // TODO: Add when compression is implemented. 1653 //return DecodeCompressed(decoder); 1654 return false; 1655 default: 1656 return false; 1657 } 1658 } 1659 1660 // Decodes a polygon by pointing the S2Loop vertices directly into the 1661 // decoder's memory buffer (which needs to persist for the lifetime of the 1662 // decoded S2Polygon). It is much faster than Decode(), but requires that 1663 // all the polygon vertices were encoded exactly using 24 bytes per vertex. 1664 // This essentially requires that the polygon was not snapped beforehand to 1665 // a given S2Cell level; otherwise this method falls back to Decode(). 1666 // 1667 // Returns true on success. 1668 // bool DecodeWithinScope(Decoder* const decoder); 1669 1670 /** 1671 * Wrapper class for indexing a polygon (see S2ShapeIndex). Once this 1672 * object is inserted into an S2ShapeIndex it is owned by that index, and 1673 * will be automatically deleted when no longer needed by the index. Note 1674 * that this class does not take ownership of the polygon itself (see 1675 * OwningShape below). You can also subtype this class to store additional 1676 * data (see S2Shape for details). 1677 * 1678 * Note that unlike S2Polygon, the edges of S2Polygon::Shape are directed 1679 * such that the polygon interior is always on the left. 1680 */ 1681 static class Shape : S2Shape { 1682 public: 1683 this() { 1684 _polygon = null; 1685 _cumulativeEdges = null; 1686 } 1687 1688 /** 1689 * Initialization. Does not take ownership of "polygon". May be called 1690 * more than once. 1691 * TODO(ericv/jrosenstock): Make "polygon" a const reference. 1692 */ 1693 this(in S2Polygon polygon) { 1694 initialize(polygon); 1695 } 1696 1697 void initialize(in S2Polygon polygon) { 1698 _polygon = polygon; 1699 _cumulativeEdges = null; 1700 _numEdges = 0; 1701 if (!polygon.isFull()) { 1702 const int kMaxLinearSearchLoops = 12; // From benchmarks. 1703 int num_loops = polygon.numLoops(); 1704 if (num_loops > kMaxLinearSearchLoops) { 1705 _cumulativeEdges = new int[num_loops]; 1706 } 1707 for (int i = 0; i < num_loops; ++i) { 1708 if (_cumulativeEdges) _cumulativeEdges[i] = _numEdges; 1709 _numEdges += polygon.loop(i).numVertices(); 1710 } 1711 } 1712 } 1713 1714 const(S2Polygon) polygon() const { 1715 return _polygon; 1716 } 1717 1718 /// S2Shape interface: 1719 final override 1720 int numEdges() const { 1721 return _numEdges; 1722 } 1723 1724 final override 1725 Edge edge(int e) const 1726 in { 1727 assert(e < numEdges()); 1728 } do { 1729 const S2Polygon p = polygon(); 1730 int i; 1731 if (_cumulativeEdges) { 1732 // "upper_bound" finds the loop just beyond the one we want. 1733 auto ranges = assumeSorted(_cumulativeEdges[0 .. p.numLoops()]).trisect(e); 1734 int start = .chain(ranges[0], ranges[1]).back(); 1735 i = cast(int) (_cumulativeEdges.length - ranges[2].length) - 1; 1736 e -= start; 1737 } else { 1738 // When the number of loops is small, linear search is faster. Most often 1739 // there is exactly one loop and the code below executes zero times. 1740 for (i = 0; e >= p.loop(i).numVertices(); ++i) { 1741 e -= p.loop(i).numVertices(); 1742 } 1743 } 1744 return Edge(p.loop(i).orientedVertex(e), p.loop(i).orientedVertex(e + 1)); 1745 } 1746 1747 final override 1748 int dimension() const { 1749 return 2; 1750 } 1751 1752 final override 1753 ReferencePoint getReferencePoint() const { 1754 import s2.s2pointutil : origin; 1755 const S2Polygon p = polygon(); 1756 bool contains_origin = false; 1757 for (int i = 0; i < p.numLoops(); ++i) { 1758 contains_origin ^= p.loop(i).containsOrigin(); 1759 } 1760 return ReferencePoint(origin(), contains_origin); 1761 } 1762 1763 final override 1764 int numChains() const { 1765 return _polygon.isFull() ? 0 : _polygon.numLoops(); 1766 } 1767 1768 final override 1769 Chain chain(int i) const 1770 in { 1771 assert(i < numChains()); 1772 } do { 1773 if (_cumulativeEdges) { 1774 return Chain(_cumulativeEdges[i], _polygon.loop(i).numVertices()); 1775 } else { 1776 int e = 0; 1777 for (int j = 0; j < i; ++j) e += _polygon.loop(j).numVertices(); 1778 return Chain(e, _polygon.loop(i).numVertices()); 1779 } 1780 } 1781 1782 final override 1783 Edge chainEdge(int i, int j) const 1784 in { 1785 assert(i < numChains()); 1786 assert(j < _polygon.loop(i).numVertices()); 1787 } do { 1788 return Edge(polygon().loop(i).orientedVertex(j), polygon().loop(i).orientedVertex(j + 1)); 1789 } 1790 1791 final override 1792 ChainPosition chainPosition(int e) const 1793 in { 1794 // TODO(ericv): Make inline to remove code duplication with GetEdge. 1795 assert(e < numEdges()); 1796 } do { 1797 const S2Polygon p = polygon(); 1798 int i; 1799 if (_cumulativeEdges) { 1800 // "upper_bound" finds the loop just beyond the one we want. 1801 //auto r = findSplitAfter!"a < b"(_cumulativeEdges[0 .. p.numLoops()], [e])[0]; 1802 auto ranges = assumeSorted(_cumulativeEdges[0 .. p.numLoops()]).trisect(e); 1803 int start = .chain(ranges[0], ranges[1]).back(); 1804 i = cast(int) (_cumulativeEdges.length - ranges[2].length) - 1; 1805 e -= start; 1806 } else { 1807 // When the number of loops is small, linear search is faster. Most often 1808 // there is exactly one loop and the code below executes zero times. 1809 for (i = 0; e >= p.loop(i).numVertices(); ++i) { 1810 e -= p.loop(i).numVertices(); 1811 } 1812 } 1813 return ChainPosition(i, e); 1814 } 1815 1816 private: 1817 /** 1818 * The total number of edges in the polygon. This is the same as 1819 * polygon_->num_vertices() except in one case (polygon_->is_full()). On 1820 * the other hand this field doesn't take up any extra space due to field 1821 * packing with S2Shape::id_. 1822 * 1823 * TODO(ericv): Consider using this field instead as an atomic<int> hint to 1824 * speed up edge location when there are a large number of loops. Also 1825 * consider changing S2Polygon::num_vertices to num_edges instead. 1826 */ 1827 int _numEdges; 1828 1829 Rebindable!(const(S2Polygon)) _polygon; 1830 1831 // An array where element "i" is the total number of edges in loops 0..i-1. 1832 // This field is only used for polygons that have a large number of loops. 1833 int[] _cumulativeEdges; 1834 } 1835 1836 // Like Shape, except that the S2Polygon is automatically deleted when this 1837 // object is deleted by the S2ShapeIndex. This is useful when an S2Polygon 1838 // is constructed solely for the purpose of indexing it. 1839 // TODO: Not needed in garbage-collected languages. 1840 // class OwningShape : public Shape { 1841 // public: 1842 // OwningShape() {} // Must call Init(). 1843 // explicit OwningShape(std::unique_ptr<const S2Polygon> polygon) 1844 // : Shape(polygon.release()) { 1845 // } 1846 // void Init(std::unique_ptr<const S2Polygon> polygon) { 1847 // Shape::Init(polygon.release()); 1848 // } 1849 // ~OwningShape() override { delete polygon(); } 1850 // }; 1851 1852 /** 1853 * Returns the built-in S2ShapeIndex associated with every S2Polygon. This 1854 * can be used in conjunction with the various S2ShapeIndex query classes 1855 * (S2ClosestEdgeQuery, S2BooleanOperation, etc) to do things beyond what is 1856 * possible with S2Polygon built-in convenience methods. 1857 * 1858 * For example, to measure the distance from one S2Polygon to another, you 1859 * can write: 1860 * S2ClosestEdgeQuery query(&polygon1.index()); 1861 * S2ClosestEdgeQuery::ShapeIndexTarget target(&polygon2.index()); 1862 * S1ChordAngle distance = query.GetDistance(&target); 1863 * 1864 * The index contains a single S2Polygon::Shape object. 1865 */ 1866 MutableS2ShapeIndex index() { 1867 return _index; 1868 } 1869 1870 private: 1871 1872 /// Given that loops_ contains a single loop, initialize all other fields. 1873 void initializeOneLoop() 1874 in { 1875 assert(numLoops() == 1); 1876 } do { 1877 S2Loop loop = _loops[0]; 1878 loop.setDepth(0); 1879 _errorInconsistentLoopOrientations = false; 1880 _numVertices = loop.numVertices(); 1881 _bound = loop.getRectBound(); 1882 _subregionBound = S2LatLngRectBounder.expandForSubregions(_bound); 1883 initializeIndex(); 1884 } 1885 1886 /// Compute num_vertices_, bound_, subregion_bound_. 1887 void initializeLoopProperties() { 1888 _numVertices = 0; 1889 _bound = S2LatLngRect.empty(); 1890 for (int i = 0; i < numLoops(); ++i) { 1891 if (loop(i).depth() == 0) { 1892 _bound = _bound.unite(loop(i).getRectBound()); 1893 } 1894 _numVertices += loop(i).numVertices(); 1895 } 1896 _subregionBound = S2LatLngRectBounder.expandForSubregions(_bound); 1897 initializeIndex(); 1898 } 1899 1900 /// Deletes the contents of the loops_ vector and resets the polygon state. 1901 void clearLoops() { 1902 clearIndex(); 1903 _loops.length = 0; 1904 _errorInconsistentLoopOrientations = false; 1905 } 1906 1907 /// Return true if there is an error in the loop nesting hierarchy. 1908 bool findLoopNestingError(ref S2Error error) { 1909 // First check that the loop depths make sense. 1910 for (int last_depth = -1, i = 0; i < numLoops(); ++i) { 1911 int depth = loop(i).depth(); 1912 if (depth < 0 || depth > last_depth + 1) { 1913 error.initialize(S2Error.Code.POLYGON_INVALID_LOOP_DEPTH, 1914 "Loop %d: invalid loop depth (%d)", i, depth); 1915 return true; 1916 } 1917 last_depth = depth; 1918 } 1919 // Then check that they correspond to the actual loop nesting. This test 1920 // is quadratic in the number of loops but the cost per iteration is small. 1921 for (int i = 0; i < numLoops(); ++i) { 1922 int last = getLastDescendant(i); 1923 for (int j = 0; j < numLoops(); ++j) { 1924 if (i == j) continue; 1925 bool nested = (j >= i + 1) && (j <= last); 1926 const bool reverse_b = false; 1927 if (loop(i).containsNonCrossingBoundary(loop(j), reverse_b) != nested) { 1928 error.initialize(S2Error.Code.POLYGON_INVALID_LOOP_NESTING, 1929 "Invalid nesting: loop %d should %scontain loop %d", 1930 i, nested ? "" : "not ", j); 1931 return true; 1932 } 1933 } 1934 } 1935 return false; 1936 } 1937 1938 /** 1939 * A map from each loop to its immediate children with respect to nesting. 1940 * This map is built during initialization of multi-loop polygons to 1941 * determine which are shells and which are holes, and then discarded. 1942 */ 1943 alias LoopMap = S2Loop[][S2Loop]; 1944 1945 void insertLoop(S2Loop new_loop, S2Loop parent, ref LoopMap loop_map) { 1946 S2Loop[]* children; 1947 for (bool done = false; !done; ) { 1948 children = &loop_map.require(parent, new S2Loop[0]); 1949 done = true; 1950 foreach (S2Loop child; *children) { 1951 if (child.containsNested(new_loop)) { 1952 parent = child; 1953 done = false; 1954 break; 1955 } 1956 } 1957 } 1958 1959 // Some of the children of the parent loop may now be children of 1960 // the new loop. 1961 S2Loop[]* new_children = &loop_map.require(new_loop, new S2Loop[0]); 1962 for (int i = 0; i < children.length;) { 1963 S2Loop child = (*children)[i]; 1964 if (new_loop.containsNested(child)) { 1965 *new_children ~= child; 1966 *children = (*children).remove(i); 1967 } else { 1968 ++i; 1969 } 1970 } 1971 *children ~= new_loop; 1972 } 1973 1974 void initializeLoops(LoopMap loop_map) { 1975 S2Loop[] loop_stack = [null]; 1976 int depth = -1; 1977 while (!loop_stack.empty()) { 1978 S2Loop loop = loop_stack.back(); 1979 loop_stack.popBack(); 1980 if (loop !is null) { 1981 depth = loop.depth(); 1982 _loops ~= loop; 1983 } 1984 if (loop !in loop_map) { 1985 continue; 1986 } 1987 S2Loop[] children = loop_map[loop]; 1988 for (int i = cast(int) children.length - 1; i >= 0; --i) { 1989 S2Loop child = children[i]; 1990 enforce(child !is null); 1991 child.setDepth(depth + 1); 1992 loop_stack ~= child; 1993 } 1994 } 1995 } 1996 1997 /** 1998 * Add the polygon's loops to the S2ShapeIndex. (The actual work of 1999 * building the index only happens when the index is first used.) 2000 */ 2001 void initializeIndex() 2002 in { 2003 assert(_index.numShapeIds() == 0); 2004 } do { 2005 _index.add(new Shape(this)); 2006 if (!S2POLYGON_LAZY_INDEXING) { 2007 _index.forceBuild(); 2008 } 2009 if (flagsS2Debug && _s2debugOverride == S2Debug.ALLOW) { 2010 // Note that FLAGS_s2debug is false in optimized builds (by default). 2011 enforce(isValid()); 2012 } 2013 } 2014 2015 /** 2016 * When the loop is modified (Invert(), or Init() called again) then the 2017 * indexing structures need to be cleared since they become invalid. 2018 */ 2019 void clearIndex() { 2020 atomicStore!(MemoryOrder.raw)(_unindexedContainsCalls, 0); 2021 _index.clear(); 2022 } 2023 2024 /// Initializes the polygon to the result of the given boolean operation. 2025 bool initializeToOperation(S2BooleanOperation.OpType op_type, 2026 S2Builder.SnapFunction snap_function, S2Polygon a, S2Polygon b) { 2027 auto options = new S2BooleanOperation.Options(); 2028 options.setSnapFunction(snap_function); 2029 auto op = new S2BooleanOperation(op_type, new S2PolygonLayer(this), options); 2030 S2Error error; 2031 if (!op.build(a._index, b._index, error)) { 2032 logger.logFatal(op_type.to!string ~ " operation failed: ", error); 2033 return false; 2034 } 2035 return true; 2036 } 2037 2038 /** 2039 * Initializes the polygon from input polygon "a" using the given S2Builder. 2040 * If the result has an empty boundary (no loops), also decides whether the 2041 * result should be the full polygon rather than the empty one based on the 2042 * area of the input polygon. (See comments in InitToApproxIntersection.) 2043 */ 2044 void initializeFromBuilder(in S2Polygon a, S2Builder builder) { 2045 builder.startLayer(new S2PolygonLayer(this)); 2046 builder.addPolygon(a); 2047 S2Error error; 2048 if (!builder.build(error)) { 2049 logger.logFatal("Could not build polygon: ", error); 2050 } 2051 // If there are no loops, check whether the result should be the full 2052 // polygon rather than the empty one. (See InitToApproxIntersection.) 2053 if (numLoops() == 0) { 2054 if (a._bound.area() > 2 * M_PI && a.getArea() > 2 * M_PI) invert(); 2055 } 2056 } 2057 2058 S2Polyline[] operationWithPolyline( 2059 S2BooleanOperation.OpType op_type, S2Builder.SnapFunction snap_function, in S2Polyline a) { 2060 auto options = new S2BooleanOperation.Options(); 2061 options.setSnapFunction(snap_function); 2062 S2Polyline[] result; 2063 S2PolylineVectorLayer.Options layer_options; 2064 layer_options.setPolylineType(S2PolylineVectorLayer.Options.PolylineType.WALK); 2065 auto op = new S2BooleanOperation( 2066 op_type, new S2PolylineVectorLayer(&result, layer_options), options); 2067 auto a_index = new MutableS2ShapeIndex(); 2068 a_index.add(new S2Polyline.Shape(a)); 2069 S2Error error; 2070 if (!op.build(a_index, _index, error)) { 2071 logger.logFatal("Polyline ", op_type.to!string, " operation failed: ", error); 2072 } 2073 return result; 2074 } 2075 2076 /** 2077 * Encode the polygon's S2Points directly as three doubles using 2078 * (40 + 43 * num_loops + 24 * num_vertices) bytes. 2079 */ 2080 void encodeLossless(ORangeT)(Encoder!ORangeT encoder) const 2081 out (; encoder.avail() >= 0) { 2082 encoder.ensure(10); // Sufficient 2083 encoder.put8(CURRENT_LOSSLESS_ENCODING_VERSION_NUMBER); 2084 // This code used to write "owns_loops_", so write "true" for compatibility. 2085 encoder.put8(true); 2086 // Encode obsolete "has_holes_" field for backwards compatibility. 2087 bool has_holes = false; 2088 for (int i = 0; i < numLoops(); ++i) { 2089 if (loop(i).isHole()) has_holes = true; 2090 } 2091 encoder.put8(has_holes); 2092 encoder.put32(cast(uint) _loops.length); 2093 2094 for (int i = 0; i < numLoops(); ++i) { 2095 loop(i).encode(encoder); 2096 } 2097 _bound.encode(encoder); 2098 } 2099 2100 /** 2101 * Decode a polygon encoded with EncodeLossless(). Used by the Decode and 2102 * DecodeWithinScope methods above. The within_scope parameter specifies 2103 * whether to call DecodeWithinScope on the loops. 2104 */ 2105 bool decodeLossless(IRangeT)(Decoder!IRangeT decoder, bool within_scope) { 2106 if (decoder.avail() < 2 * ubyte.sizeof + uint.sizeof) return false; 2107 clearLoops(); 2108 decoder.get8(); // Ignore irrelevant serialized owns_loops_ value. 2109 decoder.get8(); // Ignore irrelevant serialized has_holes_ value. 2110 // Polygons with no loops are explicitly allowed here: a newly created 2111 // polygon has zero loops and such polygons encode and decode properly. 2112 uint num_loops = decoder.get32(); 2113 if (num_loops > S2POLYGON_DECODE_MAX_NUM_LOOPS) return false; 2114 _loops.reserve(num_loops); 2115 _numVertices = 0; 2116 for (int i = 0; i < num_loops; ++i) { 2117 _loops ~= new S2Loop(); 2118 _loops.back().s2DebugOverride(s2debugOverride()); 2119 if (within_scope) { 2120 enforce("decodeWithinScope is not supported!"); 2121 // if (!loops_.back()->DecodeWithinScope(decoder)) return false; 2122 } else { 2123 if (!_loops.back().decode(decoder)) return false; 2124 } 2125 _numVertices += _loops.back().numVertices(); 2126 } 2127 if (!_bound.decode(decoder)) return false; 2128 _subregionBound = S2LatLngRectBounder.expandForSubregions(_bound); 2129 initializeIndex(); 2130 return true; 2131 } 2132 2133 // Encode the polygon's vertices using about 4 bytes / vertex plus 24 bytes / 2134 // unsnapped vertex. All the loop vertices must be converted first to the 2135 // S2XYZFaceSiTi format using S2Loop::GetXYZFaceSiTiVertices, and concatenated 2136 // in the all_vertices array. 2137 // 2138 // REQUIRES: snap_level >= 0. 2139 // void EncodeCompressed(Encoder* encoder, const S2XYZFaceSiTi* all_vertices, 2140 // int snap_level) const; 2141 2142 // Decode a polygon encoded with EncodeCompressed(). 2143 // bool DecodeCompressed(Decoder* decoder); 2144 2145 /// See comments in InitToSimplifiedInCell. 2146 static S2Polyline[] simplifyEdgesInCell( 2147 in S2Polygon a, in S2Cell cell, double tolerance_uv, S1Angle snap_radius) { 2148 auto options = new S2Builder.Options(new IdentitySnapFunction(snap_radius)); 2149 options.setSimplifyEdgeChains(true); 2150 auto builder = new S2Builder(options); 2151 // The output consists of a sequence of polylines. Polylines consisting of 2152 // interior edges are simplified using S2Builder, while polylines consisting 2153 // of boundary edges are returned unchanged. 2154 S2Polyline[] polylines; 2155 for (int i = 0; i < a.numLoops(); ++i) { 2156 const S2Loop a_loop = a.loop(i); 2157 S2Point v0 = a_loop.orientedVertex(0); 2158 ubyte mask0 = getCellEdgeIncidenceMask(cell, v0, tolerance_uv); 2159 bool in_interior = false; // Was the last edge an interior edge? 2160 for (int j = 1; j <= a_loop.numVertices(); ++j) { 2161 const S2Point v1 = a_loop.orientedVertex(j); 2162 ubyte mask1 = getCellEdgeIncidenceMask(cell, v1, tolerance_uv); 2163 if ((mask0 & mask1) != 0) { 2164 // This is an edge along the cell boundary. Such edges do not get 2165 // simplified; we add them directly to the output. (We create a 2166 // separate polyline for each edge to keep things simple.) We call 2167 // ForceVertex on all boundary vertices to ensure that they don't 2168 // move, and so that nearby interior edges are snapped to them. 2169 enforce(!in_interior); 2170 builder.forceVertex(v1); 2171 polylines ~= new S2Polyline([v0, v1]); 2172 } else { 2173 // This is an interior edge. If this is the first edge of an interior 2174 // chain, then start a new S2Builder layer. Also ensure that any 2175 // polyline vertices on the boundary do not move, so that they will 2176 // still connect with any boundary edge(s) there. 2177 if (!in_interior) { 2178 S2Polyline polyline = new S2Polyline(); 2179 builder.startLayer(new S2PolylineLayer(polyline)); 2180 polylines ~= polyline; 2181 in_interior = true; 2182 } 2183 builder.addEdge(v0, v1); 2184 if (mask1 != 0) { 2185 builder.forceVertex(v1); 2186 in_interior = false; // Terminate this polyline. 2187 } 2188 } 2189 v0 = v1; 2190 mask0 = mask1; 2191 } 2192 } 2193 S2Error error; 2194 if (!builder.build(error)) { 2195 logger.logFatal("InitToSimplifiedInCell failed: ", error); 2196 } 2197 return polylines; 2198 } 2199 2200 // Internal implementation of intersect/subtract polyline functions above. 2201 // S2Polyline[] InternalClipPolyline( 2202 // bool invert, const S2Polyline& a, S1Angle snap_radius) const; 2203 2204 /** 2205 * Defines a total ordering on S2Loops that does not depend on the cyclic 2206 * order of loop vertices. This function is used to choose which loop to 2207 * invert in the case where several loops have exactly the same area. 2208 */ 2209 static int compareLoops(in S2Loop a, in S2Loop b) { 2210 if (a.numVertices() != b.numVertices()) { 2211 return a.numVertices() - b.numVertices(); 2212 } 2213 int a_dir; 2214 int ai = a.getCanonicalFirstVertex(a_dir); 2215 int b_dir; 2216 int bi = b.getCanonicalFirstVertex(b_dir); 2217 if (a_dir != b_dir) return a_dir - b_dir; 2218 for (int n = a.numVertices(); --n >= 0; ai += a_dir, bi += b_dir) { 2219 if (a.vertex(ai) < b.vertex(bi)) return -1; 2220 if (a.vertex(ai) > b.vertex(bi)) return 1; 2221 } 2222 return 0; 2223 } 2224 2225 S2Loop[] _loops; 2226 2227 /** 2228 * Allows overriding the automatic validity checking controlled by the 2229 * --s2debug flag. 2230 */ 2231 S2Debug _s2debugOverride; 2232 2233 /** 2234 * True if InitOriented() was called and the given loops had inconsistent 2235 * orientations (i.e., it is not possible to construct a polygon such that 2236 * the interior is on the left-hand side of all loops). We need to remember 2237 * this error so that it can be returned later by FindValidationError(), 2238 * since it is not possible to detect this error once the polygon has been 2239 * initialized. This field is not preserved by Encode/Decode. 2240 */ 2241 ubyte _errorInconsistentLoopOrientations; 2242 2243 /// Cache for num_vertices(). 2244 int _numVertices; 2245 2246 /** 2247 * In general we build the index the first time it is needed, but we make an 2248 * exception for Contains(S2Point) because this method has a simple brute 2249 * force implementation that is also relatively cheap. For this one method 2250 * we keep track of the number of calls made and only build the index once 2251 * enough calls have been made that we think an index would be worthwhile. 2252 */ 2253 shared int _unindexedContainsCalls; 2254 2255 /** 2256 * "bound_" is a conservative bound on all points contained by this polygon: 2257 * if A.Contains(P), then A.bound_.Contains(S2LatLng(P)). 2258 */ 2259 S2LatLngRect _bound; 2260 2261 /** 2262 * Since "bound_" is not exact, it is possible that a polygon A contains 2263 * another polygon B whose bounds are slightly larger. "subregion_bound_" 2264 * has been expanded sufficiently to account for this error, i.e. 2265 * if A.Contains(B), then A.subregion_bound_.Contains(B.bound_). 2266 */ 2267 S2LatLngRect _subregionBound; 2268 2269 /// Spatial index containing this polygon. 2270 MutableS2ShapeIndex _index; 2271 2272 } 2273 2274 // Given a point "p" inside an S2Cell or on its boundary, return a mask 2275 // indicating which of the S2Cell edges the point lies on. All boundary 2276 // comparisons are to within a maximum "u" or "v" error of "tolerance_uv". 2277 // Bit "i" in the result is set if and only "p" is incident to the edge 2278 // corresponding to S2Cell::edge(i). 2279 private ubyte getCellEdgeIncidenceMask(in S2Cell cell, in S2Point p, double tolerance_uv) { 2280 import s2.s2coords : FaceXYZtoUV; 2281 ubyte mask = 0; 2282 R2Point uv; 2283 if (FaceXYZtoUV(cell.face(), p, uv)) { 2284 R2Rect bound = cell.getBoundUV(); 2285 if (flagsS2Debug) debug enforce(bound.expanded(tolerance_uv).contains(uv)); 2286 if (fabs(uv[1] - bound[1][0]) <= tolerance_uv) mask |= 1; 2287 if (fabs(uv[0] - bound[0][1]) <= tolerance_uv) mask |= 2; 2288 if (fabs(uv[1] - bound[1][1]) <= tolerance_uv) mask |= 4; 2289 if (fabs(uv[0] - bound[0][0]) <= tolerance_uv) mask |= 8; 2290 } 2291 return mask; 2292 } 2293 2294 // When adding a new encoding, be aware that old binaries will not 2295 // be able to decode it. 2296 private enum ubyte CURRENT_LOSSLESS_ENCODING_VERSION_NUMBER = 1; 2297 private enum ubyte CURRENT_COMPRESSED_ENCODING_VERSION_NUMBER = 4; 2298 2299 /// The upper limit on the number of loops that are allowed by the S2Polygon.decode method. 2300 private enum uint S2POLYGON_DECODE_MAX_NUM_LOOPS = 10000000;