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;