gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

loop.go (66564B)


      1 // Copyright 2015 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package s2
     16 
     17 import (
     18 	"fmt"
     19 	"io"
     20 	"math"
     21 
     22 	"github.com/golang/geo/r1"
     23 	"github.com/golang/geo/r3"
     24 	"github.com/golang/geo/s1"
     25 )
     26 
     27 // Loop represents a simple spherical polygon. It consists of a sequence
     28 // of vertices where the first vertex is implicitly connected to the
     29 // last. All loops are defined to have a CCW orientation, i.e. the interior of
     30 // the loop is on the left side of the edges. This implies that a clockwise
     31 // loop enclosing a small area is interpreted to be a CCW loop enclosing a
     32 // very large area.
     33 //
     34 // Loops are not allowed to have any duplicate vertices (whether adjacent or
     35 // not).  Non-adjacent edges are not allowed to intersect, and furthermore edges
     36 // of length 180 degrees are not allowed (i.e., adjacent vertices cannot be
     37 // antipodal). Loops must have at least 3 vertices (except for the "empty" and
     38 // "full" loops discussed below).
     39 //
     40 // There are two special loops: the "empty" loop contains no points and the
     41 // "full" loop contains all points. These loops do not have any edges, but to
     42 // preserve the invariant that every loop can be represented as a vertex
     43 // chain, they are defined as having exactly one vertex each (see EmptyLoop
     44 // and FullLoop).
     45 type Loop struct {
     46 	vertices []Point
     47 
     48 	// originInside keeps a precomputed value whether this loop contains the origin
     49 	// versus computing from the set of vertices every time.
     50 	originInside bool
     51 
     52 	// depth is the nesting depth of this Loop if it is contained by a Polygon
     53 	// or other shape and is used to determine if this loop represents a hole
     54 	// or a filled in portion.
     55 	depth int
     56 
     57 	// bound is a conservative bound on all points contained by this loop.
     58 	// If l.ContainsPoint(P), then l.bound.ContainsPoint(P).
     59 	bound Rect
     60 
     61 	// Since bound is not exact, it is possible that a loop A contains
     62 	// another loop B whose bounds are slightly larger. subregionBound
     63 	// has been expanded sufficiently to account for this error, i.e.
     64 	// if A.Contains(B), then A.subregionBound.Contains(B.bound).
     65 	subregionBound Rect
     66 
     67 	// index is the spatial index for this Loop.
     68 	index *ShapeIndex
     69 }
     70 
     71 // LoopFromPoints constructs a loop from the given points.
     72 func LoopFromPoints(pts []Point) *Loop {
     73 	l := &Loop{
     74 		vertices: pts,
     75 		index:    NewShapeIndex(),
     76 	}
     77 
     78 	l.initOriginAndBound()
     79 	return l
     80 }
     81 
     82 // LoopFromCell constructs a loop corresponding to the given cell.
     83 //
     84 // Note that the loop and cell *do not* contain exactly the same set of
     85 // points, because Loop and Cell have slightly different definitions of
     86 // point containment. For example, a Cell vertex is contained by all
     87 // four neighboring Cells, but it is contained by exactly one of four
     88 // Loops constructed from those cells. As another example, the cell
     89 // coverings of cell and LoopFromCell(cell) will be different, because the
     90 // loop contains points on its boundary that actually belong to other cells
     91 // (i.e., the covering will include a layer of neighboring cells).
     92 func LoopFromCell(c Cell) *Loop {
     93 	l := &Loop{
     94 		vertices: []Point{
     95 			c.Vertex(0),
     96 			c.Vertex(1),
     97 			c.Vertex(2),
     98 			c.Vertex(3),
     99 		},
    100 		index: NewShapeIndex(),
    101 	}
    102 
    103 	l.initOriginAndBound()
    104 	return l
    105 }
    106 
    107 // These two points are used for the special Empty and Full loops.
    108 var (
    109 	emptyLoopPoint = Point{r3.Vector{X: 0, Y: 0, Z: 1}}
    110 	fullLoopPoint  = Point{r3.Vector{X: 0, Y: 0, Z: -1}}
    111 )
    112 
    113 // EmptyLoop returns a special "empty" loop.
    114 func EmptyLoop() *Loop {
    115 	return LoopFromPoints([]Point{emptyLoopPoint})
    116 }
    117 
    118 // FullLoop returns a special "full" loop.
    119 func FullLoop() *Loop {
    120 	return LoopFromPoints([]Point{fullLoopPoint})
    121 }
    122 
    123 // initOriginAndBound sets the origin containment for the given point and then calls
    124 // the initialization for the bounds objects and the internal index.
    125 func (l *Loop) initOriginAndBound() {
    126 	if len(l.vertices) < 3 {
    127 		// Check for the special "empty" and "full" loops (which have one vertex).
    128 		if !l.isEmptyOrFull() {
    129 			l.originInside = false
    130 			return
    131 		}
    132 
    133 		// This is the special empty or full loop, so the origin depends on if
    134 		// the vertex is in the southern hemisphere or not.
    135 		l.originInside = l.vertices[0].Z < 0
    136 	} else {
    137 		// Point containment testing is done by counting edge crossings starting
    138 		// at a fixed point on the sphere (OriginPoint). We need to know whether
    139 		// the reference point (OriginPoint) is inside or outside the loop before
    140 		// we can construct the ShapeIndex. We do this by first guessing that
    141 		// it is outside, and then seeing whether we get the correct containment
    142 		// result for vertex 1. If the result is incorrect, the origin must be
    143 		// inside the loop.
    144 		//
    145 		// A loop with consecutive vertices A,B,C contains vertex B if and only if
    146 		// the fixed vector R = B.Ortho is contained by the wedge ABC. The
    147 		// wedge is closed at A and open at C, i.e. the point B is inside the loop
    148 		// if A = R but not if C = R. This convention is required for compatibility
    149 		// with VertexCrossing. (Note that we can't use OriginPoint
    150 		// as the fixed vector because of the possibility that B == OriginPoint.)
    151 		l.originInside = false
    152 		v1Inside := OrderedCCW(Point{l.vertices[1].Ortho()}, l.vertices[0], l.vertices[2], l.vertices[1])
    153 		if v1Inside != l.ContainsPoint(l.vertices[1]) {
    154 			l.originInside = true
    155 		}
    156 	}
    157 
    158 	// We *must* call initBound before initializing the index, because
    159 	// initBound calls ContainsPoint which does a bounds check before using
    160 	// the index.
    161 	l.initBound()
    162 
    163 	// Create a new index and add us to it.
    164 	l.index = NewShapeIndex()
    165 	l.index.Add(l)
    166 }
    167 
    168 // initBound sets up the approximate bounding Rects for this loop.
    169 func (l *Loop) initBound() {
    170 	if len(l.vertices) == 0 {
    171 		*l = *EmptyLoop()
    172 		return
    173 	}
    174 	// Check for the special "empty" and "full" loops.
    175 	if l.isEmptyOrFull() {
    176 		if l.IsEmpty() {
    177 			l.bound = EmptyRect()
    178 		} else {
    179 			l.bound = FullRect()
    180 		}
    181 		l.subregionBound = l.bound
    182 		return
    183 	}
    184 
    185 	// The bounding rectangle of a loop is not necessarily the same as the
    186 	// bounding rectangle of its vertices. First, the maximal latitude may be
    187 	// attained along the interior of an edge. Second, the loop may wrap
    188 	// entirely around the sphere (e.g. a loop that defines two revolutions of a
    189 	// candy-cane stripe). Third, the loop may include one or both poles.
    190 	// Note that a small clockwise loop near the equator contains both poles.
    191 	bounder := NewRectBounder()
    192 	for i := 0; i <= len(l.vertices); i++ { // add vertex 0 twice
    193 		bounder.AddPoint(l.Vertex(i))
    194 	}
    195 	b := bounder.RectBound()
    196 
    197 	if l.ContainsPoint(Point{r3.Vector{0, 0, 1}}) {
    198 		b = Rect{r1.Interval{b.Lat.Lo, math.Pi / 2}, s1.FullInterval()}
    199 	}
    200 	// If a loop contains the south pole, then either it wraps entirely
    201 	// around the sphere (full longitude range), or it also contains the
    202 	// north pole in which case b.Lng.IsFull() due to the test above.
    203 	// Either way, we only need to do the south pole containment test if
    204 	// b.Lng.IsFull().
    205 	if b.Lng.IsFull() && l.ContainsPoint(Point{r3.Vector{0, 0, -1}}) {
    206 		b.Lat.Lo = -math.Pi / 2
    207 	}
    208 	l.bound = b
    209 	l.subregionBound = ExpandForSubregions(l.bound)
    210 }
    211 
    212 // Validate checks whether this is a valid loop.
    213 func (l *Loop) Validate() error {
    214 	if err := l.findValidationErrorNoIndex(); err != nil {
    215 		return err
    216 	}
    217 
    218 	// Check for intersections between non-adjacent edges (including at vertices)
    219 	// TODO(roberts): Once shapeutil gets findAnyCrossing uncomment this.
    220 	// return findAnyCrossing(l.index)
    221 
    222 	return nil
    223 }
    224 
    225 // findValidationErrorNoIndex reports whether this is not a valid loop, but
    226 // skips checks that would require a ShapeIndex to be built for the loop. This
    227 // is primarily used by Polygon to do validation so it doesn't trigger the
    228 // creation of unneeded ShapeIndices.
    229 func (l *Loop) findValidationErrorNoIndex() error {
    230 	// All vertices must be unit length.
    231 	for i, v := range l.vertices {
    232 		if !v.IsUnit() {
    233 			return fmt.Errorf("vertex %d is not unit length", i)
    234 		}
    235 	}
    236 
    237 	// Loops must have at least 3 vertices (except for empty and full).
    238 	if len(l.vertices) < 3 {
    239 		if l.isEmptyOrFull() {
    240 			return nil // Skip remaining tests.
    241 		}
    242 		return fmt.Errorf("non-empty, non-full loops must have at least 3 vertices")
    243 	}
    244 
    245 	// Loops are not allowed to have any duplicate vertices or edge crossings.
    246 	// We split this check into two parts. First we check that no edge is
    247 	// degenerate (identical endpoints). Then we check that there are no
    248 	// intersections between non-adjacent edges (including at vertices). The
    249 	// second check needs the ShapeIndex, so it does not fall within the scope
    250 	// of this method.
    251 	for i, v := range l.vertices {
    252 		if v == l.Vertex(i+1) {
    253 			return fmt.Errorf("edge %d is degenerate (duplicate vertex)", i)
    254 		}
    255 
    256 		// Antipodal vertices are not allowed.
    257 		if other := (Point{l.Vertex(i + 1).Mul(-1)}); v == other {
    258 			return fmt.Errorf("vertices %d and %d are antipodal", i,
    259 				(i+1)%len(l.vertices))
    260 		}
    261 	}
    262 
    263 	return nil
    264 }
    265 
    266 // Contains reports whether the region contained by this loop is a superset of the
    267 // region contained by the given other loop.
    268 func (l *Loop) Contains(o *Loop) bool {
    269 	// For a loop A to contain the loop B, all of the following must
    270 	// be true:
    271 	//
    272 	//  (1) There are no edge crossings between A and B except at vertices.
    273 	//
    274 	//  (2) At every vertex that is shared between A and B, the local edge
    275 	//      ordering implies that A contains B.
    276 	//
    277 	//  (3) If there are no shared vertices, then A must contain a vertex of B
    278 	//      and B must not contain a vertex of A. (An arbitrary vertex may be
    279 	//      chosen in each case.)
    280 	//
    281 	// The second part of (3) is necessary to detect the case of two loops whose
    282 	// union is the entire sphere, i.e. two loops that contains each other's
    283 	// boundaries but not each other's interiors.
    284 	if !l.subregionBound.Contains(o.bound) {
    285 		return false
    286 	}
    287 
    288 	// Special cases to handle either loop being empty or full.
    289 	if l.isEmptyOrFull() || o.isEmptyOrFull() {
    290 		return l.IsFull() || o.IsEmpty()
    291 	}
    292 
    293 	// Check whether there are any edge crossings, and also check the loop
    294 	// relationship at any shared vertices.
    295 	relation := &containsRelation{}
    296 	if hasCrossingRelation(l, o, relation) {
    297 		return false
    298 	}
    299 
    300 	// There are no crossings, and if there are any shared vertices then A
    301 	// contains B locally at each shared vertex.
    302 	if relation.foundSharedVertex {
    303 		return true
    304 	}
    305 
    306 	// Since there are no edge intersections or shared vertices, we just need to
    307 	// test condition (3) above. We can skip this test if we discovered that A
    308 	// contains at least one point of B while checking for edge crossings.
    309 	if !l.ContainsPoint(o.Vertex(0)) {
    310 		return false
    311 	}
    312 
    313 	// We still need to check whether (A union B) is the entire sphere.
    314 	// Normally this check is very cheap due to the bounding box precondition.
    315 	if (o.subregionBound.Contains(l.bound) || o.bound.Union(l.bound).IsFull()) &&
    316 		o.ContainsPoint(l.Vertex(0)) {
    317 		return false
    318 	}
    319 	return true
    320 }
    321 
    322 // Intersects reports whether the region contained by this loop intersects the region
    323 // contained by the other loop.
    324 func (l *Loop) Intersects(o *Loop) bool {
    325 	// Given two loops, A and B, A.Intersects(B) if and only if !A.Complement().Contains(B).
    326 	//
    327 	// This code is similar to Contains, but is optimized for the case
    328 	// where both loops enclose less than half of the sphere.
    329 	if !l.bound.Intersects(o.bound) {
    330 		return false
    331 	}
    332 
    333 	// Check whether there are any edge crossings, and also check the loop
    334 	// relationship at any shared vertices.
    335 	relation := &intersectsRelation{}
    336 	if hasCrossingRelation(l, o, relation) {
    337 		return true
    338 	}
    339 	if relation.foundSharedVertex {
    340 		return false
    341 	}
    342 
    343 	// Since there are no edge intersections or shared vertices, the loops
    344 	// intersect only if A contains B, B contains A, or the two loops contain
    345 	// each other's boundaries.  These checks are usually cheap because of the
    346 	// bounding box preconditions.  Note that neither loop is empty (because of
    347 	// the bounding box check above), so it is safe to access vertex(0).
    348 
    349 	// Check whether A contains B, or A and B contain each other's boundaries.
    350 	// (Note that A contains all the vertices of B in either case.)
    351 	if l.subregionBound.Contains(o.bound) || l.bound.Union(o.bound).IsFull() {
    352 		if l.ContainsPoint(o.Vertex(0)) {
    353 			return true
    354 		}
    355 	}
    356 	// Check whether B contains A.
    357 	if o.subregionBound.Contains(l.bound) {
    358 		if o.ContainsPoint(l.Vertex(0)) {
    359 			return true
    360 		}
    361 	}
    362 	return false
    363 }
    364 
    365 // Equal reports whether two loops have the same vertices in the same linear order
    366 // (i.e., cyclic rotations are not allowed).
    367 func (l *Loop) Equal(other *Loop) bool {
    368 	if len(l.vertices) != len(other.vertices) {
    369 		return false
    370 	}
    371 
    372 	for i, v := range l.vertices {
    373 		if v != other.Vertex(i) {
    374 			return false
    375 		}
    376 	}
    377 	return true
    378 }
    379 
    380 // BoundaryEqual reports whether the two loops have the same boundary. This is
    381 // true if and only if the loops have the same vertices in the same cyclic order
    382 // (i.e., the vertices may be cyclically rotated). The empty and full loops are
    383 // considered to have different boundaries.
    384 func (l *Loop) BoundaryEqual(o *Loop) bool {
    385 	if len(l.vertices) != len(o.vertices) {
    386 		return false
    387 	}
    388 
    389 	// Special case to handle empty or full loops.  Since they have the same
    390 	// number of vertices, if one loop is empty/full then so is the other.
    391 	if l.isEmptyOrFull() {
    392 		return l.IsEmpty() == o.IsEmpty()
    393 	}
    394 
    395 	// Loop through the vertices to find the first of ours that matches the
    396 	// starting vertex of the other loop. Use that offset to then 'align' the
    397 	// vertices for comparison.
    398 	for offset, vertex := range l.vertices {
    399 		if vertex == o.Vertex(0) {
    400 			// There is at most one starting offset since loop vertices are unique.
    401 			for i := 0; i < len(l.vertices); i++ {
    402 				if l.Vertex(i+offset) != o.Vertex(i) {
    403 					return false
    404 				}
    405 			}
    406 			return true
    407 		}
    408 	}
    409 	return false
    410 }
    411 
    412 // compareBoundary returns +1 if this loop contains the boundary of the other loop,
    413 // -1 if it excludes the boundary of the other, and 0 if the boundaries of the two
    414 // loops cross. Shared edges are handled as follows:
    415 //
    416 //   If XY is a shared edge, define Reversed(XY) to be true if XY
    417 //     appears in opposite directions in both loops.
    418 //   Then this loop contains XY if and only if Reversed(XY) == the other loop is a hole.
    419 //   (Intuitively, this checks whether this loop contains a vanishingly small region
    420 //   extending from the boundary of the other toward the interior of the polygon to
    421 //   which the other belongs.)
    422 //
    423 // This function is used for testing containment and intersection of
    424 // multi-loop polygons. Note that this method is not symmetric, since the
    425 // result depends on the direction of this loop but not on the direction of
    426 // the other loop (in the absence of shared edges).
    427 //
    428 // This requires that neither loop is empty, and if other loop IsFull, then it must not
    429 // be a hole.
    430 func (l *Loop) compareBoundary(o *Loop) int {
    431 	// The bounds must intersect for containment or crossing.
    432 	if !l.bound.Intersects(o.bound) {
    433 		return -1
    434 	}
    435 
    436 	// Full loops are handled as though the loop surrounded the entire sphere.
    437 	if l.IsFull() {
    438 		return 1
    439 	}
    440 	if o.IsFull() {
    441 		return -1
    442 	}
    443 
    444 	// Check whether there are any edge crossings, and also check the loop
    445 	// relationship at any shared vertices.
    446 	relation := newCompareBoundaryRelation(o.IsHole())
    447 	if hasCrossingRelation(l, o, relation) {
    448 		return 0
    449 	}
    450 	if relation.foundSharedVertex {
    451 		if relation.containsEdge {
    452 			return 1
    453 		}
    454 		return -1
    455 	}
    456 
    457 	// There are no edge intersections or shared vertices, so we can check
    458 	// whether A contains an arbitrary vertex of B.
    459 	if l.ContainsPoint(o.Vertex(0)) {
    460 		return 1
    461 	}
    462 	return -1
    463 }
    464 
    465 // ContainsOrigin reports true if this loop contains s2.OriginPoint().
    466 func (l *Loop) ContainsOrigin() bool {
    467 	return l.originInside
    468 }
    469 
    470 // ReferencePoint returns the reference point for this loop.
    471 func (l *Loop) ReferencePoint() ReferencePoint {
    472 	return OriginReferencePoint(l.originInside)
    473 }
    474 
    475 // NumEdges returns the number of edges in this shape.
    476 func (l *Loop) NumEdges() int {
    477 	if l.isEmptyOrFull() {
    478 		return 0
    479 	}
    480 	return len(l.vertices)
    481 }
    482 
    483 // Edge returns the endpoints for the given edge index.
    484 func (l *Loop) Edge(i int) Edge {
    485 	return Edge{l.Vertex(i), l.Vertex(i + 1)}
    486 }
    487 
    488 // NumChains reports the number of contiguous edge chains in the Loop.
    489 func (l *Loop) NumChains() int {
    490 	if l.IsEmpty() {
    491 		return 0
    492 	}
    493 	return 1
    494 }
    495 
    496 // Chain returns the i-th edge chain in the Shape.
    497 func (l *Loop) Chain(chainID int) Chain {
    498 	return Chain{0, l.NumEdges()}
    499 }
    500 
    501 // ChainEdge returns the j-th edge of the i-th edge chain.
    502 func (l *Loop) ChainEdge(chainID, offset int) Edge {
    503 	return Edge{l.Vertex(offset), l.Vertex(offset + 1)}
    504 }
    505 
    506 // ChainPosition returns a ChainPosition pair (i, j) such that edgeID is the
    507 // j-th edge of the Loop.
    508 func (l *Loop) ChainPosition(edgeID int) ChainPosition {
    509 	return ChainPosition{0, edgeID}
    510 }
    511 
    512 // Dimension returns the dimension of the geometry represented by this Loop.
    513 func (l *Loop) Dimension() int { return 2 }
    514 
    515 func (l *Loop) typeTag() typeTag { return typeTagNone }
    516 
    517 func (l *Loop) privateInterface() {}
    518 
    519 // IsEmpty reports true if this is the special empty loop that contains no points.
    520 func (l *Loop) IsEmpty() bool {
    521 	return l.isEmptyOrFull() && !l.ContainsOrigin()
    522 }
    523 
    524 // IsFull reports true if this is the special full loop that contains all points.
    525 func (l *Loop) IsFull() bool {
    526 	return l.isEmptyOrFull() && l.ContainsOrigin()
    527 }
    528 
    529 // isEmptyOrFull reports true if this loop is either the "empty" or "full" special loops.
    530 func (l *Loop) isEmptyOrFull() bool {
    531 	return len(l.vertices) == 1
    532 }
    533 
    534 // Vertices returns the vertices in the loop.
    535 func (l *Loop) Vertices() []Point {
    536 	return l.vertices
    537 }
    538 
    539 // RectBound returns a tight bounding rectangle. If the loop contains the point,
    540 // the bound also contains it.
    541 func (l *Loop) RectBound() Rect {
    542 	return l.bound
    543 }
    544 
    545 // CapBound returns a bounding cap that may have more padding than the corresponding
    546 // RectBound. The bound is conservative such that if the loop contains a point P,
    547 // the bound also contains it.
    548 func (l *Loop) CapBound() Cap {
    549 	return l.bound.CapBound()
    550 }
    551 
    552 // Vertex returns the vertex for the given index. For convenience, the vertex indices
    553 // wrap automatically for methods that do index math such as Edge.
    554 // i.e., Vertex(NumEdges() + n) is the same as Vertex(n).
    555 func (l *Loop) Vertex(i int) Point {
    556 	return l.vertices[i%len(l.vertices)]
    557 }
    558 
    559 // OrientedVertex returns the vertex in reverse order if the loop represents a polygon
    560 // hole. For example, arguments 0, 1, 2 are mapped to vertices n-1, n-2, n-3, where
    561 // n == len(vertices). This ensures that the interior of the polygon is always to
    562 // the left of the vertex chain.
    563 //
    564 // This requires: 0 <= i < 2 * len(vertices)
    565 func (l *Loop) OrientedVertex(i int) Point {
    566 	j := i - len(l.vertices)
    567 	if j < 0 {
    568 		j = i
    569 	}
    570 	if l.IsHole() {
    571 		j = len(l.vertices) - 1 - j
    572 	}
    573 	return l.Vertex(j)
    574 }
    575 
    576 // NumVertices returns the number of vertices in this loop.
    577 func (l *Loop) NumVertices() int {
    578 	return len(l.vertices)
    579 }
    580 
    581 // bruteForceContainsPoint reports if the given point is contained by this loop.
    582 // This method does not use the ShapeIndex, so it is only preferable below a certain
    583 // size of loop.
    584 func (l *Loop) bruteForceContainsPoint(p Point) bool {
    585 	origin := OriginPoint()
    586 	inside := l.originInside
    587 	crosser := NewChainEdgeCrosser(origin, p, l.Vertex(0))
    588 	for i := 1; i <= len(l.vertices); i++ { // add vertex 0 twice
    589 		inside = inside != crosser.EdgeOrVertexChainCrossing(l.Vertex(i))
    590 	}
    591 	return inside
    592 }
    593 
    594 // ContainsPoint returns true if the loop contains the point.
    595 func (l *Loop) ContainsPoint(p Point) bool {
    596 	if !l.index.IsFresh() && !l.bound.ContainsPoint(p) {
    597 		return false
    598 	}
    599 
    600 	// For small loops it is faster to just check all the crossings.  We also
    601 	// use this method during loop initialization because InitOriginAndBound()
    602 	// calls Contains() before InitIndex().  Otherwise, we keep track of the
    603 	// number of calls to Contains() and only build the index when enough calls
    604 	// have been made so that we think it is worth the effort.  Note that the
    605 	// code below is structured so that if many calls are made in parallel only
    606 	// one thread builds the index, while the rest continue using brute force
    607 	// until the index is actually available.
    608 
    609 	const maxBruteForceVertices = 32
    610 	// TODO(roberts): add unindexed contains calls tracking
    611 
    612 	if len(l.index.shapes) == 0 || // Index has not been initialized yet.
    613 		len(l.vertices) <= maxBruteForceVertices {
    614 		return l.bruteForceContainsPoint(p)
    615 	}
    616 
    617 	// Otherwise, look up the point in the index.
    618 	it := l.index.Iterator()
    619 	if !it.LocatePoint(p) {
    620 		return false
    621 	}
    622 	return l.iteratorContainsPoint(it, p)
    623 }
    624 
    625 // ContainsCell reports whether the given Cell is contained by this Loop.
    626 func (l *Loop) ContainsCell(target Cell) bool {
    627 	it := l.index.Iterator()
    628 	relation := it.LocateCellID(target.ID())
    629 
    630 	// If "target" is disjoint from all index cells, it is not contained.
    631 	// Similarly, if "target" is subdivided into one or more index cells then it
    632 	// is not contained, since index cells are subdivided only if they (nearly)
    633 	// intersect a sufficient number of edges.  (But note that if "target" itself
    634 	// is an index cell then it may be contained, since it could be a cell with
    635 	// no edges in the loop interior.)
    636 	if relation != Indexed {
    637 		return false
    638 	}
    639 
    640 	// Otherwise check if any edges intersect "target".
    641 	if l.boundaryApproxIntersects(it, target) {
    642 		return false
    643 	}
    644 
    645 	// Otherwise check if the loop contains the center of "target".
    646 	return l.iteratorContainsPoint(it, target.Center())
    647 }
    648 
    649 // IntersectsCell reports whether this Loop intersects the given cell.
    650 func (l *Loop) IntersectsCell(target Cell) bool {
    651 	it := l.index.Iterator()
    652 	relation := it.LocateCellID(target.ID())
    653 
    654 	// If target does not overlap any index cell, there is no intersection.
    655 	if relation == Disjoint {
    656 		return false
    657 	}
    658 	// If target is subdivided into one or more index cells, there is an
    659 	// intersection to within the ShapeIndex error bound (see Contains).
    660 	if relation == Subdivided {
    661 		return true
    662 	}
    663 	// If target is an index cell, there is an intersection because index cells
    664 	// are created only if they have at least one edge or they are entirely
    665 	// contained by the loop.
    666 	if it.CellID() == target.id {
    667 		return true
    668 	}
    669 	// Otherwise check if any edges intersect target.
    670 	if l.boundaryApproxIntersects(it, target) {
    671 		return true
    672 	}
    673 	// Otherwise check if the loop contains the center of target.
    674 	return l.iteratorContainsPoint(it, target.Center())
    675 }
    676 
    677 // CellUnionBound computes a covering of the Loop.
    678 func (l *Loop) CellUnionBound() []CellID {
    679 	return l.CapBound().CellUnionBound()
    680 }
    681 
    682 // boundaryApproxIntersects reports if the loop's boundary intersects target.
    683 // It may also return true when the loop boundary does not intersect target but
    684 // some edge comes within the worst-case error tolerance.
    685 //
    686 // This requires that it.Locate(target) returned Indexed.
    687 func (l *Loop) boundaryApproxIntersects(it *ShapeIndexIterator, target Cell) bool {
    688 	aClipped := it.IndexCell().findByShapeID(0)
    689 
    690 	// If there are no edges, there is no intersection.
    691 	if len(aClipped.edges) == 0 {
    692 		return false
    693 	}
    694 
    695 	// We can save some work if target is the index cell itself.
    696 	if it.CellID() == target.ID() {
    697 		return true
    698 	}
    699 
    700 	// Otherwise check whether any of the edges intersect target.
    701 	maxError := (faceClipErrorUVCoord + intersectsRectErrorUVDist)
    702 	bound := target.BoundUV().ExpandedByMargin(maxError)
    703 	for _, ai := range aClipped.edges {
    704 		v0, v1, ok := ClipToPaddedFace(l.Vertex(ai), l.Vertex(ai+1), target.Face(), maxError)
    705 		if ok && edgeIntersectsRect(v0, v1, bound) {
    706 			return true
    707 		}
    708 	}
    709 	return false
    710 }
    711 
    712 // iteratorContainsPoint reports if the iterator that is positioned at the ShapeIndexCell
    713 // that may contain p, contains the point p.
    714 func (l *Loop) iteratorContainsPoint(it *ShapeIndexIterator, p Point) bool {
    715 	// Test containment by drawing a line segment from the cell center to the
    716 	// given point and counting edge crossings.
    717 	aClipped := it.IndexCell().findByShapeID(0)
    718 	inside := aClipped.containsCenter
    719 	if len(aClipped.edges) > 0 {
    720 		center := it.Center()
    721 		crosser := NewEdgeCrosser(center, p)
    722 		aiPrev := -2
    723 		for _, ai := range aClipped.edges {
    724 			if ai != aiPrev+1 {
    725 				crosser.RestartAt(l.Vertex(ai))
    726 			}
    727 			aiPrev = ai
    728 			inside = inside != crosser.EdgeOrVertexChainCrossing(l.Vertex(ai+1))
    729 		}
    730 	}
    731 	return inside
    732 }
    733 
    734 // RegularLoop creates a loop with the given number of vertices, all
    735 // located on a circle of the specified radius around the given center.
    736 func RegularLoop(center Point, radius s1.Angle, numVertices int) *Loop {
    737 	return RegularLoopForFrame(getFrame(center), radius, numVertices)
    738 }
    739 
    740 // RegularLoopForFrame creates a loop centered around the z-axis of the given
    741 // coordinate frame, with the first vertex in the direction of the positive x-axis.
    742 func RegularLoopForFrame(frame matrix3x3, radius s1.Angle, numVertices int) *Loop {
    743 	return LoopFromPoints(regularPointsForFrame(frame, radius, numVertices))
    744 }
    745 
    746 // CanonicalFirstVertex returns a first index and a direction (either +1 or -1)
    747 // such that the vertex sequence (first, first+dir, ..., first+(n-1)*dir) does
    748 // not change when the loop vertex order is rotated or inverted. This allows the
    749 // loop vertices to be traversed in a canonical order. The return values are
    750 // chosen such that (first, ..., first+n*dir) are in the range [0, 2*n-1] as
    751 // expected by the Vertex method.
    752 func (l *Loop) CanonicalFirstVertex() (firstIdx, direction int) {
    753 	firstIdx = 0
    754 	n := len(l.vertices)
    755 	for i := 1; i < n; i++ {
    756 		if l.Vertex(i).Cmp(l.Vertex(firstIdx).Vector) == -1 {
    757 			firstIdx = i
    758 		}
    759 	}
    760 
    761 	// 0 <= firstIdx <= n-1, so (firstIdx+n*dir) <= 2*n-1.
    762 	if l.Vertex(firstIdx+1).Cmp(l.Vertex(firstIdx+n-1).Vector) == -1 {
    763 		return firstIdx, 1
    764 	}
    765 
    766 	// n <= firstIdx <= 2*n-1, so (firstIdx+n*dir) >= 0.
    767 	firstIdx += n
    768 	return firstIdx, -1
    769 }
    770 
    771 // TurningAngle returns the sum of the turning angles at each vertex. The return
    772 // value is positive if the loop is counter-clockwise, negative if the loop is
    773 // clockwise, and zero if the loop is a great circle. Degenerate and
    774 // nearly-degenerate loops are handled consistently with Sign. So for example,
    775 // if a loop has zero area (i.e., it is a very small CCW loop) then the turning
    776 // angle will always be negative.
    777 //
    778 // This quantity is also called the "geodesic curvature" of the loop.
    779 func (l *Loop) TurningAngle() float64 {
    780 	// For empty and full loops, we return the limit value as the loop area
    781 	// approaches 0 or 4*Pi respectively.
    782 	if l.isEmptyOrFull() {
    783 		if l.ContainsOrigin() {
    784 			return -2 * math.Pi
    785 		}
    786 		return 2 * math.Pi
    787 	}
    788 
    789 	// Don't crash even if the loop is not well-defined.
    790 	if len(l.vertices) < 3 {
    791 		return 0
    792 	}
    793 
    794 	// To ensure that we get the same result when the vertex order is rotated,
    795 	// and that the result is negated when the vertex order is reversed, we need
    796 	// to add up the individual turn angles in a consistent order. (In general,
    797 	// adding up a set of numbers in a different order can change the sum due to
    798 	// rounding errors.)
    799 	//
    800 	// Furthermore, if we just accumulate an ordinary sum then the worst-case
    801 	// error is quadratic in the number of vertices. (This can happen with
    802 	// spiral shapes, where the partial sum of the turning angles can be linear
    803 	// in the number of vertices.) To avoid this we use the Kahan summation
    804 	// algorithm (http://en.wikipedia.org/wiki/Kahan_summation_algorithm).
    805 	n := len(l.vertices)
    806 	i, dir := l.CanonicalFirstVertex()
    807 	sum := TurnAngle(l.Vertex((i+n-dir)%n), l.Vertex(i), l.Vertex((i+dir)%n))
    808 
    809 	compensation := s1.Angle(0)
    810 	for n-1 > 0 {
    811 		i += dir
    812 		angle := TurnAngle(l.Vertex(i-dir), l.Vertex(i), l.Vertex(i+dir))
    813 		oldSum := sum
    814 		angle += compensation
    815 		sum += angle
    816 		compensation = (oldSum - sum) + angle
    817 		n--
    818 	}
    819 
    820 	const maxCurvature = 2*math.Pi - 4*dblEpsilon
    821 
    822 	return math.Max(-maxCurvature, math.Min(maxCurvature, float64(dir)*float64(sum+compensation)))
    823 }
    824 
    825 // turningAngleMaxError return the maximum error in TurningAngle. The value is not
    826 // constant; it depends on the loop.
    827 func (l *Loop) turningAngleMaxError() float64 {
    828 	// The maximum error can be bounded as follows:
    829 	//   3.00 * dblEpsilon    for RobustCrossProd(b, a)
    830 	//   3.00 * dblEpsilon    for RobustCrossProd(c, b)
    831 	//   3.25 * dblEpsilon    for Angle()
    832 	//   2.00 * dblEpsilon    for each addition in the Kahan summation
    833 	//   ------------------
    834 	//  11.25 * dblEpsilon
    835 	maxErrorPerVertex := 11.25 * dblEpsilon
    836 	return maxErrorPerVertex * float64(len(l.vertices))
    837 }
    838 
    839 // IsHole reports whether this loop represents a hole in its containing polygon.
    840 func (l *Loop) IsHole() bool { return l.depth&1 != 0 }
    841 
    842 // Sign returns -1 if this Loop represents a hole in its containing polygon, and +1 otherwise.
    843 func (l *Loop) Sign() int {
    844 	if l.IsHole() {
    845 		return -1
    846 	}
    847 	return 1
    848 }
    849 
    850 // IsNormalized reports whether the loop area is at most 2*pi. Degenerate loops are
    851 // handled consistently with Sign, i.e., if a loop can be
    852 // expressed as the union of degenerate or nearly-degenerate CCW triangles,
    853 // then it will always be considered normalized.
    854 func (l *Loop) IsNormalized() bool {
    855 	// Optimization: if the longitude span is less than 180 degrees, then the
    856 	// loop covers less than half the sphere and is therefore normalized.
    857 	if l.bound.Lng.Length() < math.Pi {
    858 		return true
    859 	}
    860 
    861 	// We allow some error so that hemispheres are always considered normalized.
    862 	// TODO(roberts): This is no longer required by the Polygon implementation,
    863 	// so alternatively we could create the invariant that a loop is normalized
    864 	// if and only if its complement is not normalized.
    865 	return l.TurningAngle() >= -l.turningAngleMaxError()
    866 }
    867 
    868 // Normalize inverts the loop if necessary so that the area enclosed by the loop
    869 // is at most 2*pi.
    870 func (l *Loop) Normalize() {
    871 	if !l.IsNormalized() {
    872 		l.Invert()
    873 	}
    874 }
    875 
    876 // Invert reverses the order of the loop vertices, effectively complementing the
    877 // region represented by the loop. For example, the loop ABCD (with edges
    878 // AB, BC, CD, DA) becomes the loop DCBA (with edges DC, CB, BA, AD).
    879 // Notice that the last edge is the same in both cases except that its
    880 // direction has been reversed.
    881 func (l *Loop) Invert() {
    882 	l.index.Reset()
    883 	if l.isEmptyOrFull() {
    884 		if l.IsFull() {
    885 			l.vertices[0] = emptyLoopPoint
    886 		} else {
    887 			l.vertices[0] = fullLoopPoint
    888 		}
    889 	} else {
    890 		// For non-special loops, reverse the slice of vertices.
    891 		for i := len(l.vertices)/2 - 1; i >= 0; i-- {
    892 			opp := len(l.vertices) - 1 - i
    893 			l.vertices[i], l.vertices[opp] = l.vertices[opp], l.vertices[i]
    894 		}
    895 	}
    896 
    897 	// originInside must be set correctly before building the ShapeIndex.
    898 	l.originInside = !l.originInside
    899 	if l.bound.Lat.Lo > -math.Pi/2 && l.bound.Lat.Hi < math.Pi/2 {
    900 		// The complement of this loop contains both poles.
    901 		l.bound = FullRect()
    902 		l.subregionBound = l.bound
    903 	} else {
    904 		l.initBound()
    905 	}
    906 	l.index.Add(l)
    907 }
    908 
    909 // findVertex returns the index of the vertex at the given Point in the range
    910 // 1..numVertices, and a boolean indicating if a vertex was found.
    911 func (l *Loop) findVertex(p Point) (index int, ok bool) {
    912 	const notFound = 0
    913 	if len(l.vertices) < 10 {
    914 		// Exhaustive search for loops below a small threshold.
    915 		for i := 1; i <= len(l.vertices); i++ {
    916 			if l.Vertex(i) == p {
    917 				return i, true
    918 			}
    919 		}
    920 		return notFound, false
    921 	}
    922 
    923 	it := l.index.Iterator()
    924 	if !it.LocatePoint(p) {
    925 		return notFound, false
    926 	}
    927 
    928 	aClipped := it.IndexCell().findByShapeID(0)
    929 	for i := aClipped.numEdges() - 1; i >= 0; i-- {
    930 		ai := aClipped.edges[i]
    931 		if l.Vertex(ai) == p {
    932 			if ai == 0 {
    933 				return len(l.vertices), true
    934 			}
    935 			return ai, true
    936 		}
    937 
    938 		if l.Vertex(ai+1) == p {
    939 			return ai + 1, true
    940 		}
    941 	}
    942 	return notFound, false
    943 }
    944 
    945 // ContainsNested reports whether the given loops is contained within this loop.
    946 // This function does not test for edge intersections. The two loops must meet
    947 // all of the Polygon requirements; for example this implies that their
    948 // boundaries may not cross or have any shared edges (although they may have
    949 // shared vertices).
    950 func (l *Loop) ContainsNested(other *Loop) bool {
    951 	if !l.subregionBound.Contains(other.bound) {
    952 		return false
    953 	}
    954 
    955 	// Special cases to handle either loop being empty or full.  Also bail out
    956 	// when B has no vertices to avoid heap overflow on the vertex(1) call
    957 	// below.  (This method is called during polygon initialization before the
    958 	// client has an opportunity to call IsValid().)
    959 	if l.isEmptyOrFull() || other.NumVertices() < 2 {
    960 		return l.IsFull() || other.IsEmpty()
    961 	}
    962 
    963 	// We are given that A and B do not share any edges, and that either one
    964 	// loop contains the other or they do not intersect.
    965 	m, ok := l.findVertex(other.Vertex(1))
    966 	if !ok {
    967 		// Since other.vertex(1) is not shared, we can check whether A contains it.
    968 		return l.ContainsPoint(other.Vertex(1))
    969 	}
    970 
    971 	// Check whether the edge order around other.Vertex(1) is compatible with
    972 	// A containing B.
    973 	return WedgeContains(l.Vertex(m-1), l.Vertex(m), l.Vertex(m+1), other.Vertex(0), other.Vertex(2))
    974 }
    975 
    976 // surfaceIntegralFloat64 computes the oriented surface integral of some quantity f(x)
    977 // over the loop interior, given a function f(A,B,C) that returns the
    978 // corresponding integral over the spherical triangle ABC. Here "oriented
    979 // surface integral" means:
    980 //
    981 // (1) f(A,B,C) must be the integral of f if ABC is counterclockwise,
    982 //     and the integral of -f if ABC is clockwise.
    983 //
    984 // (2) The result of this function is *either* the integral of f over the
    985 //     loop interior, or the integral of (-f) over the loop exterior.
    986 //
    987 // Note that there are at least two common situations where it easy to work
    988 // around property (2) above:
    989 //
    990 //  - If the integral of f over the entire sphere is zero, then it doesn't
    991 //    matter which case is returned because they are always equal.
    992 //
    993 //  - If f is non-negative, then it is easy to detect when the integral over
    994 //    the loop exterior has been returned, and the integral over the loop
    995 //    interior can be obtained by adding the integral of f over the entire
    996 //    unit sphere (a constant) to the result.
    997 //
    998 // Any changes to this method may need corresponding changes to surfaceIntegralPoint as well.
    999 func (l *Loop) surfaceIntegralFloat64(f func(a, b, c Point) float64) float64 {
   1000 	// We sum f over a collection T of oriented triangles, possibly
   1001 	// overlapping. Let the sign of a triangle be +1 if it is CCW and -1
   1002 	// otherwise, and let the sign of a point x be the sum of the signs of the
   1003 	// triangles containing x. Then the collection of triangles T is chosen
   1004 	// such that either:
   1005 	//
   1006 	//  (1) Each point in the loop interior has sign +1, and sign 0 otherwise; or
   1007 	//  (2) Each point in the loop exterior has sign -1, and sign 0 otherwise.
   1008 	//
   1009 	// The triangles basically consist of a fan from vertex 0 to every loop
   1010 	// edge that does not include vertex 0. These triangles will always satisfy
   1011 	// either (1) or (2). However, what makes this a bit tricky is that
   1012 	// spherical edges become numerically unstable as their length approaches
   1013 	// 180 degrees. Of course there is not much we can do if the loop itself
   1014 	// contains such edges, but we would like to make sure that all the triangle
   1015 	// edges under our control (i.e., the non-loop edges) are stable. For
   1016 	// example, consider a loop around the equator consisting of four equally
   1017 	// spaced points. This is a well-defined loop, but we cannot just split it
   1018 	// into two triangles by connecting vertex 0 to vertex 2.
   1019 	//
   1020 	// We handle this type of situation by moving the origin of the triangle fan
   1021 	// whenever we are about to create an unstable edge. We choose a new
   1022 	// location for the origin such that all relevant edges are stable. We also
   1023 	// create extra triangles with the appropriate orientation so that the sum
   1024 	// of the triangle signs is still correct at every point.
   1025 
   1026 	// The maximum length of an edge for it to be considered numerically stable.
   1027 	// The exact value is fairly arbitrary since it depends on the stability of
   1028 	// the function f. The value below is quite conservative but could be
   1029 	// reduced further if desired.
   1030 	const maxLength = math.Pi - 1e-5
   1031 
   1032 	var sum float64
   1033 	origin := l.Vertex(0)
   1034 	for i := 1; i+1 < len(l.vertices); i++ {
   1035 		// Let V_i be vertex(i), let O be the current origin, and let length(A,B)
   1036 		// be the length of edge (A,B). At the start of each loop iteration, the
   1037 		// "leading edge" of the triangle fan is (O,V_i), and we want to extend
   1038 		// the triangle fan so that the leading edge is (O,V_i+1).
   1039 		//
   1040 		// Invariants:
   1041 		//  1. length(O,V_i) < maxLength for all (i > 1).
   1042 		//  2. Either O == V_0, or O is approximately perpendicular to V_0.
   1043 		//  3. "sum" is the oriented integral of f over the area defined by
   1044 		//     (O, V_0, V_1, ..., V_i).
   1045 		if l.Vertex(i+1).Angle(origin.Vector) > maxLength {
   1046 			// We are about to create an unstable edge, so choose a new origin O'
   1047 			// for the triangle fan.
   1048 			oldOrigin := origin
   1049 			if origin == l.Vertex(0) {
   1050 				// The following point is well-separated from V_i and V_0 (and
   1051 				// therefore V_i+1 as well).
   1052 				origin = Point{l.Vertex(0).PointCross(l.Vertex(i)).Normalize()}
   1053 			} else if l.Vertex(i).Angle(l.Vertex(0).Vector) < maxLength {
   1054 				// All edges of the triangle (O, V_0, V_i) are stable, so we can
   1055 				// revert to using V_0 as the origin.
   1056 				origin = l.Vertex(0)
   1057 			} else {
   1058 				// (O, V_i+1) and (V_0, V_i) are antipodal pairs, and O and V_0 are
   1059 				// perpendicular. Therefore V_0.CrossProd(O) is approximately
   1060 				// perpendicular to all of {O, V_0, V_i, V_i+1}, and we can choose
   1061 				// this point O' as the new origin.
   1062 				origin = Point{l.Vertex(0).Cross(oldOrigin.Vector)}
   1063 
   1064 				// Advance the edge (V_0,O) to (V_0,O').
   1065 				sum += f(l.Vertex(0), oldOrigin, origin)
   1066 			}
   1067 			// Advance the edge (O,V_i) to (O',V_i).
   1068 			sum += f(oldOrigin, l.Vertex(i), origin)
   1069 		}
   1070 		// Advance the edge (O,V_i) to (O,V_i+1).
   1071 		sum += f(origin, l.Vertex(i), l.Vertex(i+1))
   1072 	}
   1073 	// If the origin is not V_0, we need to sum one more triangle.
   1074 	if origin != l.Vertex(0) {
   1075 		// Advance the edge (O,V_n-1) to (O,V_0).
   1076 		sum += f(origin, l.Vertex(len(l.vertices)-1), l.Vertex(0))
   1077 	}
   1078 	return sum
   1079 }
   1080 
   1081 // surfaceIntegralPoint mirrors the surfaceIntegralFloat64 method but over Points;
   1082 // see that method for commentary. The C++ version uses a templated method.
   1083 // Any changes to this method may need corresponding changes to surfaceIntegralFloat64 as well.
   1084 func (l *Loop) surfaceIntegralPoint(f func(a, b, c Point) Point) Point {
   1085 	const maxLength = math.Pi - 1e-5
   1086 	var sum r3.Vector
   1087 
   1088 	origin := l.Vertex(0)
   1089 	for i := 1; i+1 < len(l.vertices); i++ {
   1090 		if l.Vertex(i+1).Angle(origin.Vector) > maxLength {
   1091 			oldOrigin := origin
   1092 			if origin == l.Vertex(0) {
   1093 				origin = Point{l.Vertex(0).PointCross(l.Vertex(i)).Normalize()}
   1094 			} else if l.Vertex(i).Angle(l.Vertex(0).Vector) < maxLength {
   1095 				origin = l.Vertex(0)
   1096 			} else {
   1097 				origin = Point{l.Vertex(0).Cross(oldOrigin.Vector)}
   1098 				sum = sum.Add(f(l.Vertex(0), oldOrigin, origin).Vector)
   1099 			}
   1100 			sum = sum.Add(f(oldOrigin, l.Vertex(i), origin).Vector)
   1101 		}
   1102 		sum = sum.Add(f(origin, l.Vertex(i), l.Vertex(i+1)).Vector)
   1103 	}
   1104 	if origin != l.Vertex(0) {
   1105 		sum = sum.Add(f(origin, l.Vertex(len(l.vertices)-1), l.Vertex(0)).Vector)
   1106 	}
   1107 	return Point{sum}
   1108 }
   1109 
   1110 // Area returns the area of the loop interior, i.e. the region on the left side of
   1111 // the loop. The return value is between 0 and 4*pi. (Note that the return
   1112 // value is not affected by whether this loop is a "hole" or a "shell".)
   1113 func (l *Loop) Area() float64 {
   1114 	// It is surprisingly difficult to compute the area of a loop robustly. The
   1115 	// main issues are (1) whether degenerate loops are considered to be CCW or
   1116 	// not (i.e., whether their area is close to 0 or 4*pi), and (2) computing
   1117 	// the areas of small loops with good relative accuracy.
   1118 	//
   1119 	// With respect to degeneracies, we would like Area to be consistent
   1120 	// with ContainsPoint in that loops that contain many points
   1121 	// should have large areas, and loops that contain few points should have
   1122 	// small areas. For example, if a degenerate triangle is considered CCW
   1123 	// according to s2predicates Sign, then it will contain very few points and
   1124 	// its area should be approximately zero. On the other hand if it is
   1125 	// considered clockwise, then it will contain virtually all points and so
   1126 	// its area should be approximately 4*pi.
   1127 	//
   1128 	// More precisely, let U be the set of Points for which IsUnitLength
   1129 	// is true, let P(U) be the projection of those points onto the mathematical
   1130 	// unit sphere, and let V(P(U)) be the Voronoi diagram of the projected
   1131 	// points. Then for every loop x, we would like Area to approximately
   1132 	// equal the sum of the areas of the Voronoi regions of the points p for
   1133 	// which x.ContainsPoint(p) is true.
   1134 	//
   1135 	// The second issue is that we want to compute the area of small loops
   1136 	// accurately. This requires having good relative precision rather than
   1137 	// good absolute precision. For example, if the area of a loop is 1e-12 and
   1138 	// the error is 1e-15, then the area only has 3 digits of accuracy. (For
   1139 	// reference, 1e-12 is about 40 square meters on the surface of the earth.)
   1140 	// We would like to have good relative accuracy even for small loops.
   1141 	//
   1142 	// To achieve these goals, we combine two different methods of computing the
   1143 	// area. This first method is based on the Gauss-Bonnet theorem, which says
   1144 	// that the area enclosed by the loop equals 2*pi minus the total geodesic
   1145 	// curvature of the loop (i.e., the sum of the "turning angles" at all the
   1146 	// loop vertices). The big advantage of this method is that as long as we
   1147 	// use Sign to compute the turning angle at each vertex, then
   1148 	// degeneracies are always handled correctly. In other words, if a
   1149 	// degenerate loop is CCW according to the symbolic perturbations used by
   1150 	// Sign, then its turning angle will be approximately 2*pi.
   1151 	//
   1152 	// The disadvantage of the Gauss-Bonnet method is that its absolute error is
   1153 	// about 2e-15 times the number of vertices (see turningAngleMaxError).
   1154 	// So, it cannot compute the area of small loops accurately.
   1155 	//
   1156 	// The second method is based on splitting the loop into triangles and
   1157 	// summing the area of each triangle. To avoid the difficulty and expense
   1158 	// of decomposing the loop into a union of non-overlapping triangles,
   1159 	// instead we compute a signed sum over triangles that may overlap (see the
   1160 	// comments for surfaceIntegral). The advantage of this method
   1161 	// is that the area of each triangle can be computed with much better
   1162 	// relative accuracy (using l'Huilier's theorem). The disadvantage is that
   1163 	// the result is a signed area: CCW loops may yield a small positive value,
   1164 	// while CW loops may yield a small negative value (which is converted to a
   1165 	// positive area by adding 4*pi). This means that small errors in computing
   1166 	// the signed area may translate into a very large error in the result (if
   1167 	// the sign of the sum is incorrect).
   1168 	//
   1169 	// So, our strategy is to combine these two methods as follows. First we
   1170 	// compute the area using the "signed sum over triangles" approach (since it
   1171 	// is generally more accurate). We also estimate the maximum error in this
   1172 	// result. If the signed area is too close to zero (i.e., zero is within
   1173 	// the error bounds), then we double-check the sign of the result using the
   1174 	// Gauss-Bonnet method. (In fact we just call IsNormalized, which is
   1175 	// based on this method.) If the two methods disagree, we return either 0
   1176 	// or 4*pi based on the result of IsNormalized. Otherwise we return the
   1177 	// area that we computed originally.
   1178 	if l.isEmptyOrFull() {
   1179 		if l.ContainsOrigin() {
   1180 			return 4 * math.Pi
   1181 		}
   1182 		return 0
   1183 	}
   1184 	area := l.surfaceIntegralFloat64(SignedArea)
   1185 
   1186 	// TODO(roberts): This error estimate is very approximate. There are two
   1187 	// issues: (1) SignedArea needs some improvements to ensure that its error
   1188 	// is actually never higher than GirardArea, and (2) although the number of
   1189 	// triangles in the sum is typically N-2, in theory it could be as high as
   1190 	// 2*N for pathological inputs. But in other respects this error bound is
   1191 	// very conservative since it assumes that the maximum error is achieved on
   1192 	// every triangle.
   1193 	maxError := l.turningAngleMaxError()
   1194 
   1195 	// The signed area should be between approximately -4*pi and 4*pi.
   1196 	if area < 0 {
   1197 		// We have computed the negative of the area of the loop exterior.
   1198 		area += 4 * math.Pi
   1199 	}
   1200 
   1201 	if area > 4*math.Pi {
   1202 		area = 4 * math.Pi
   1203 	}
   1204 	if area < 0 {
   1205 		area = 0
   1206 	}
   1207 
   1208 	// If the area is close enough to zero or 4*pi so that the loop orientation
   1209 	// is ambiguous, then we compute the loop orientation explicitly.
   1210 	if area < maxError && !l.IsNormalized() {
   1211 		return 4 * math.Pi
   1212 	} else if area > (4*math.Pi-maxError) && l.IsNormalized() {
   1213 		return 0
   1214 	}
   1215 
   1216 	return area
   1217 }
   1218 
   1219 // Centroid returns the true centroid of the loop multiplied by the area of the
   1220 // loop. The result is not unit length, so you may want to normalize it. Also
   1221 // note that in general, the centroid may not be contained by the loop.
   1222 //
   1223 // We prescale by the loop area for two reasons: (1) it is cheaper to
   1224 // compute this way, and (2) it makes it easier to compute the centroid of
   1225 // more complicated shapes (by splitting them into disjoint regions and
   1226 // adding their centroids).
   1227 //
   1228 // Note that the return value is not affected by whether this loop is a
   1229 // "hole" or a "shell".
   1230 func (l *Loop) Centroid() Point {
   1231 	// surfaceIntegralPoint() returns either the integral of position over loop
   1232 	// interior, or the negative of the integral of position over the loop
   1233 	// exterior. But these two values are the same (!), because the integral of
   1234 	// position over the entire sphere is (0, 0, 0).
   1235 	return l.surfaceIntegralPoint(TrueCentroid)
   1236 }
   1237 
   1238 // Encode encodes the Loop.
   1239 func (l Loop) Encode(w io.Writer) error {
   1240 	e := &encoder{w: w}
   1241 	l.encode(e)
   1242 	return e.err
   1243 }
   1244 
   1245 func (l Loop) encode(e *encoder) {
   1246 	e.writeInt8(encodingVersion)
   1247 	e.writeUint32(uint32(len(l.vertices)))
   1248 	for _, v := range l.vertices {
   1249 		e.writeFloat64(v.X)
   1250 		e.writeFloat64(v.Y)
   1251 		e.writeFloat64(v.Z)
   1252 	}
   1253 
   1254 	e.writeBool(l.originInside)
   1255 	e.writeInt32(int32(l.depth))
   1256 
   1257 	// Encode the bound.
   1258 	l.bound.encode(e)
   1259 }
   1260 
   1261 // Decode decodes a loop.
   1262 func (l *Loop) Decode(r io.Reader) error {
   1263 	*l = Loop{}
   1264 	d := &decoder{r: asByteReader(r)}
   1265 	l.decode(d)
   1266 	return d.err
   1267 }
   1268 
   1269 func (l *Loop) decode(d *decoder) {
   1270 	version := int8(d.readUint8())
   1271 	if d.err != nil {
   1272 		return
   1273 	}
   1274 	if version != encodingVersion {
   1275 		d.err = fmt.Errorf("cannot decode version %d", version)
   1276 		return
   1277 	}
   1278 
   1279 	// Empty loops are explicitly allowed here: a newly created loop has zero vertices
   1280 	// and such loops encode and decode properly.
   1281 	nvertices := d.readUint32()
   1282 	if nvertices > maxEncodedVertices {
   1283 		if d.err == nil {
   1284 			d.err = fmt.Errorf("too many vertices (%d; max is %d)", nvertices, maxEncodedVertices)
   1285 
   1286 		}
   1287 		return
   1288 	}
   1289 	l.vertices = make([]Point, nvertices)
   1290 	for i := range l.vertices {
   1291 		l.vertices[i].X = d.readFloat64()
   1292 		l.vertices[i].Y = d.readFloat64()
   1293 		l.vertices[i].Z = d.readFloat64()
   1294 	}
   1295 	l.index = NewShapeIndex()
   1296 	l.originInside = d.readBool()
   1297 	l.depth = int(d.readUint32())
   1298 	l.bound.decode(d)
   1299 	l.subregionBound = ExpandForSubregions(l.bound)
   1300 
   1301 	l.index.Add(l)
   1302 }
   1303 
   1304 // Bitmasks to read from properties.
   1305 const (
   1306 	originInside = 1 << iota
   1307 	boundEncoded
   1308 )
   1309 
   1310 func (l *Loop) xyzFaceSiTiVertices() []xyzFaceSiTi {
   1311 	ret := make([]xyzFaceSiTi, len(l.vertices))
   1312 	for i, v := range l.vertices {
   1313 		ret[i].xyz = v
   1314 		ret[i].face, ret[i].si, ret[i].ti, ret[i].level = xyzToFaceSiTi(v)
   1315 	}
   1316 	return ret
   1317 }
   1318 
   1319 func (l *Loop) encodeCompressed(e *encoder, snapLevel int, vertices []xyzFaceSiTi) {
   1320 	if len(l.vertices) != len(vertices) {
   1321 		panic("encodeCompressed: vertices must be the same length as l.vertices")
   1322 	}
   1323 	if len(vertices) > maxEncodedVertices {
   1324 		if e.err == nil {
   1325 			e.err = fmt.Errorf("too many vertices (%d; max is %d)", len(vertices), maxEncodedVertices)
   1326 		}
   1327 		return
   1328 	}
   1329 	e.writeUvarint(uint64(len(vertices)))
   1330 	encodePointsCompressed(e, vertices, snapLevel)
   1331 
   1332 	props := l.compressedEncodingProperties()
   1333 	e.writeUvarint(props)
   1334 	e.writeUvarint(uint64(l.depth))
   1335 	if props&boundEncoded != 0 {
   1336 		l.bound.encode(e)
   1337 	}
   1338 }
   1339 
   1340 func (l *Loop) compressedEncodingProperties() uint64 {
   1341 	var properties uint64
   1342 	if l.originInside {
   1343 		properties |= originInside
   1344 	}
   1345 
   1346 	// Write whether there is a bound so we can change the threshold later.
   1347 	// Recomputing the bound multiplies the decode time taken per vertex
   1348 	// by a factor of about 3.5.  Without recomputing the bound, decode
   1349 	// takes approximately 125 ns / vertex.  A loop with 63 vertices
   1350 	// encoded without the bound will take ~30us to decode, which is
   1351 	// acceptable.  At ~3.5 bytes / vertex without the bound, adding
   1352 	// the bound will increase the size by <15%, which is also acceptable.
   1353 	const minVerticesForBound = 64
   1354 	if len(l.vertices) >= minVerticesForBound {
   1355 		properties |= boundEncoded
   1356 	}
   1357 
   1358 	return properties
   1359 }
   1360 
   1361 func (l *Loop) decodeCompressed(d *decoder, snapLevel int) {
   1362 	nvertices := d.readUvarint()
   1363 	if d.err != nil {
   1364 		return
   1365 	}
   1366 	if nvertices > maxEncodedVertices {
   1367 		d.err = fmt.Errorf("too many vertices (%d; max is %d)", nvertices, maxEncodedVertices)
   1368 		return
   1369 	}
   1370 	l.vertices = make([]Point, nvertices)
   1371 	decodePointsCompressed(d, snapLevel, l.vertices)
   1372 	properties := d.readUvarint()
   1373 
   1374 	// Make sure values are valid before using.
   1375 	if d.err != nil {
   1376 		return
   1377 	}
   1378 
   1379 	l.index = NewShapeIndex()
   1380 	l.originInside = (properties & originInside) != 0
   1381 
   1382 	l.depth = int(d.readUvarint())
   1383 
   1384 	if (properties & boundEncoded) != 0 {
   1385 		l.bound.decode(d)
   1386 		if d.err != nil {
   1387 			return
   1388 		}
   1389 		l.subregionBound = ExpandForSubregions(l.bound)
   1390 	} else {
   1391 		l.initBound()
   1392 	}
   1393 
   1394 	l.index.Add(l)
   1395 }
   1396 
   1397 // crossingTarget is an enum representing the possible crossing target cases for relations.
   1398 type crossingTarget int
   1399 
   1400 const (
   1401 	crossingTargetDontCare crossingTarget = iota
   1402 	crossingTargetDontCross
   1403 	crossingTargetCross
   1404 )
   1405 
   1406 // loopRelation defines the interface for checking a type of relationship between two loops.
   1407 // Some examples of relations are Contains, Intersects, or CompareBoundary.
   1408 type loopRelation interface {
   1409 	// Optionally, aCrossingTarget and bCrossingTarget can specify an early-exit
   1410 	// condition for the loop relation. If any point P is found such that
   1411 	//
   1412 	//   A.ContainsPoint(P) == aCrossingTarget() &&
   1413 	//   B.ContainsPoint(P) == bCrossingTarget()
   1414 	//
   1415 	// then the loop relation is assumed to be the same as if a pair of crossing
   1416 	// edges were found. For example, the ContainsPoint relation has
   1417 	//
   1418 	//   aCrossingTarget() == crossingTargetDontCross
   1419 	//   bCrossingTarget() == crossingTargetCross
   1420 	//
   1421 	// because if A.ContainsPoint(P) == false and B.ContainsPoint(P) == true
   1422 	// for any point P, then it is equivalent to finding an edge crossing (i.e.,
   1423 	// since Contains returns false in both cases).
   1424 	//
   1425 	// Loop relations that do not have an early-exit condition of this form
   1426 	// should return crossingTargetDontCare for both crossing targets.
   1427 
   1428 	// aCrossingTarget reports whether loop A crosses the target point with
   1429 	// the given relation type.
   1430 	aCrossingTarget() crossingTarget
   1431 	// bCrossingTarget reports whether loop B crosses the target point with
   1432 	// the given relation type.
   1433 	bCrossingTarget() crossingTarget
   1434 
   1435 	// wedgesCross reports if a shared vertex ab1 and the two associated wedges
   1436 	// (a0, ab1, b2) and (b0, ab1, b2) are equivalent to an edge crossing.
   1437 	// The loop relation is also allowed to maintain its own internal state, and
   1438 	// can return true if it observes any sequence of wedges that are equivalent
   1439 	// to an edge crossing.
   1440 	wedgesCross(a0, ab1, a2, b0, b2 Point) bool
   1441 }
   1442 
   1443 // loopCrosser is a helper type for determining whether two loops cross.
   1444 // It is instantiated twice for each pair of loops to be tested, once for the
   1445 // pair (A,B) and once for the pair (B,A), in order to be able to process
   1446 // edges in either loop nesting order.
   1447 type loopCrosser struct {
   1448 	a, b            *Loop
   1449 	relation        loopRelation
   1450 	swapped         bool
   1451 	aCrossingTarget crossingTarget
   1452 	bCrossingTarget crossingTarget
   1453 
   1454 	// state maintained by startEdge and edgeCrossesCell.
   1455 	crosser    *EdgeCrosser
   1456 	aj, bjPrev int
   1457 
   1458 	// temporary data declared here to avoid repeated memory allocations.
   1459 	bQuery *CrossingEdgeQuery
   1460 	bCells []*ShapeIndexCell
   1461 }
   1462 
   1463 // newLoopCrosser creates a loopCrosser from the given values. If swapped is true,
   1464 // the loops A and B have been swapped. This affects how arguments are passed to
   1465 // the given loop relation, since for example A.Contains(B) is not the same as
   1466 // B.Contains(A).
   1467 func newLoopCrosser(a, b *Loop, relation loopRelation, swapped bool) *loopCrosser {
   1468 	l := &loopCrosser{
   1469 		a:               a,
   1470 		b:               b,
   1471 		relation:        relation,
   1472 		swapped:         swapped,
   1473 		aCrossingTarget: relation.aCrossingTarget(),
   1474 		bCrossingTarget: relation.bCrossingTarget(),
   1475 		bQuery:          NewCrossingEdgeQuery(b.index),
   1476 	}
   1477 	if swapped {
   1478 		l.aCrossingTarget, l.bCrossingTarget = l.bCrossingTarget, l.aCrossingTarget
   1479 	}
   1480 
   1481 	return l
   1482 }
   1483 
   1484 // startEdge sets the crossers state for checking the given edge of loop A.
   1485 func (l *loopCrosser) startEdge(aj int) {
   1486 	l.crosser = NewEdgeCrosser(l.a.Vertex(aj), l.a.Vertex(aj+1))
   1487 	l.aj = aj
   1488 	l.bjPrev = -2
   1489 }
   1490 
   1491 // edgeCrossesCell reports whether the current edge of loop A has any crossings with
   1492 // edges of the index cell of loop B.
   1493 func (l *loopCrosser) edgeCrossesCell(bClipped *clippedShape) bool {
   1494 	// Test the current edge of A against all edges of bClipped
   1495 	bNumEdges := bClipped.numEdges()
   1496 	for j := 0; j < bNumEdges; j++ {
   1497 		bj := bClipped.edges[j]
   1498 		if bj != l.bjPrev+1 {
   1499 			l.crosser.RestartAt(l.b.Vertex(bj))
   1500 		}
   1501 		l.bjPrev = bj
   1502 		if crossing := l.crosser.ChainCrossingSign(l.b.Vertex(bj + 1)); crossing == DoNotCross {
   1503 			continue
   1504 		} else if crossing == Cross {
   1505 			return true
   1506 		}
   1507 
   1508 		// We only need to check each shared vertex once, so we only
   1509 		// consider the case where l.aVertex(l.aj+1) == l.b.Vertex(bj+1).
   1510 		if l.a.Vertex(l.aj+1) == l.b.Vertex(bj+1) {
   1511 			if l.swapped {
   1512 				if l.relation.wedgesCross(l.b.Vertex(bj), l.b.Vertex(bj+1), l.b.Vertex(bj+2), l.a.Vertex(l.aj), l.a.Vertex(l.aj+2)) {
   1513 					return true
   1514 				}
   1515 			} else {
   1516 				if l.relation.wedgesCross(l.a.Vertex(l.aj), l.a.Vertex(l.aj+1), l.a.Vertex(l.aj+2), l.b.Vertex(bj), l.b.Vertex(bj+2)) {
   1517 					return true
   1518 				}
   1519 			}
   1520 		}
   1521 	}
   1522 
   1523 	return false
   1524 }
   1525 
   1526 // cellCrossesCell reports whether there are any edge crossings or wedge crossings
   1527 // within the two given cells.
   1528 func (l *loopCrosser) cellCrossesCell(aClipped, bClipped *clippedShape) bool {
   1529 	// Test all edges of aClipped against all edges of bClipped.
   1530 	for _, edge := range aClipped.edges {
   1531 		l.startEdge(edge)
   1532 		if l.edgeCrossesCell(bClipped) {
   1533 			return true
   1534 		}
   1535 	}
   1536 
   1537 	return false
   1538 }
   1539 
   1540 // cellCrossesAnySubcell reports whether given an index cell of A, if there are any
   1541 // edge or wedge crossings with any index cell of B contained within bID.
   1542 func (l *loopCrosser) cellCrossesAnySubcell(aClipped *clippedShape, bID CellID) bool {
   1543 	// Test all edges of aClipped against all edges of B. The relevant B
   1544 	// edges are guaranteed to be children of bID, which lets us find the
   1545 	// correct index cells more efficiently.
   1546 	bRoot := PaddedCellFromCellID(bID, 0)
   1547 	for _, aj := range aClipped.edges {
   1548 		// Use an CrossingEdgeQuery starting at bRoot to find the index cells
   1549 		// of B that might contain crossing edges.
   1550 		l.bCells = l.bQuery.getCells(l.a.Vertex(aj), l.a.Vertex(aj+1), bRoot)
   1551 		if len(l.bCells) == 0 {
   1552 			continue
   1553 		}
   1554 		l.startEdge(aj)
   1555 		for c := 0; c < len(l.bCells); c++ {
   1556 			if l.edgeCrossesCell(l.bCells[c].shapes[0]) {
   1557 				return true
   1558 			}
   1559 		}
   1560 	}
   1561 
   1562 	return false
   1563 }
   1564 
   1565 // hasCrossing reports whether given two iterators positioned such that
   1566 // ai.cellID().ContainsCellID(bi.cellID()), there is an edge or wedge crossing
   1567 // anywhere within ai.cellID(). This function advances bi only past ai.cellID().
   1568 func (l *loopCrosser) hasCrossing(ai, bi *rangeIterator) bool {
   1569 	// If ai.CellID() intersects many edges of B, then it is faster to use
   1570 	// CrossingEdgeQuery to narrow down the candidates. But if it intersects
   1571 	// only a few edges, it is faster to check all the crossings directly.
   1572 	// We handle this by advancing bi and keeping track of how many edges we
   1573 	// would need to test.
   1574 	const edgeQueryMinEdges = 20 // Tuned from benchmarks.
   1575 	var totalEdges int
   1576 	l.bCells = nil
   1577 
   1578 	for {
   1579 		if n := bi.it.IndexCell().shapes[0].numEdges(); n > 0 {
   1580 			totalEdges += n
   1581 			if totalEdges >= edgeQueryMinEdges {
   1582 				// There are too many edges to test them directly, so use CrossingEdgeQuery.
   1583 				if l.cellCrossesAnySubcell(ai.it.IndexCell().shapes[0], ai.cellID()) {
   1584 					return true
   1585 				}
   1586 				bi.seekBeyond(ai)
   1587 				return false
   1588 			}
   1589 			l.bCells = append(l.bCells, bi.indexCell())
   1590 		}
   1591 		bi.next()
   1592 		if bi.cellID() > ai.rangeMax {
   1593 			break
   1594 		}
   1595 	}
   1596 
   1597 	// Test all the edge crossings directly.
   1598 	for _, c := range l.bCells {
   1599 		if l.cellCrossesCell(ai.it.IndexCell().shapes[0], c.shapes[0]) {
   1600 			return true
   1601 		}
   1602 	}
   1603 
   1604 	return false
   1605 }
   1606 
   1607 // containsCenterMatches reports if the clippedShapes containsCenter boolean corresponds
   1608 // to the crossing target type given. (This is to work around C++ allowing false == 0,
   1609 // true == 1 type implicit conversions and comparisons)
   1610 func containsCenterMatches(a *clippedShape, target crossingTarget) bool {
   1611 	return (!a.containsCenter && target == crossingTargetDontCross) ||
   1612 		(a.containsCenter && target == crossingTargetCross)
   1613 }
   1614 
   1615 // hasCrossingRelation reports whether given two iterators positioned such that
   1616 // ai.cellID().ContainsCellID(bi.cellID()), there is a crossing relationship
   1617 // anywhere within ai.cellID(). Specifically, this method returns true if there
   1618 // is an edge crossing, a wedge crossing, or a point P that matches both relations
   1619 // crossing targets. This function advances both iterators past ai.cellID.
   1620 func (l *loopCrosser) hasCrossingRelation(ai, bi *rangeIterator) bool {
   1621 	aClipped := ai.it.IndexCell().shapes[0]
   1622 	if aClipped.numEdges() != 0 {
   1623 		// The current cell of A has at least one edge, so check for crossings.
   1624 		if l.hasCrossing(ai, bi) {
   1625 			return true
   1626 		}
   1627 		ai.next()
   1628 		return false
   1629 	}
   1630 
   1631 	if containsCenterMatches(aClipped, l.aCrossingTarget) {
   1632 		// The crossing target for A is not satisfied, so we skip over these cells of B.
   1633 		bi.seekBeyond(ai)
   1634 		ai.next()
   1635 		return false
   1636 	}
   1637 
   1638 	// All points within ai.cellID() satisfy the crossing target for A, so it's
   1639 	// worth iterating through the cells of B to see whether any cell
   1640 	// centers also satisfy the crossing target for B.
   1641 	for bi.cellID() <= ai.rangeMax {
   1642 		bClipped := bi.it.IndexCell().shapes[0]
   1643 		if containsCenterMatches(bClipped, l.bCrossingTarget) {
   1644 			return true
   1645 		}
   1646 		bi.next()
   1647 	}
   1648 	ai.next()
   1649 	return false
   1650 }
   1651 
   1652 // hasCrossingRelation checks all edges of loop A for intersection against all edges
   1653 // of loop B and reports if there are any that satisfy the given relation. If there
   1654 // is any shared vertex, the wedges centered at this vertex are sent to the given
   1655 // relation to be tested.
   1656 //
   1657 // If the two loop boundaries cross, this method is guaranteed to return
   1658 // true. It also returns true in certain cases if the loop relationship is
   1659 // equivalent to crossing. For example, if the relation is Contains and a
   1660 // point P is found such that B contains P but A does not contain P, this
   1661 // method will return true to indicate that the result is the same as though
   1662 // a pair of crossing edges were found (since Contains returns false in
   1663 // both cases).
   1664 //
   1665 // See Contains, Intersects and CompareBoundary for the three uses of this function.
   1666 func hasCrossingRelation(a, b *Loop, relation loopRelation) bool {
   1667 	// We look for CellID ranges where the indexes of A and B overlap, and
   1668 	// then test those edges for crossings.
   1669 	ai := newRangeIterator(a.index)
   1670 	bi := newRangeIterator(b.index)
   1671 
   1672 	ab := newLoopCrosser(a, b, relation, false) // Tests edges of A against B
   1673 	ba := newLoopCrosser(b, a, relation, true)  // Tests edges of B against A
   1674 
   1675 	for !ai.done() || !bi.done() {
   1676 		if ai.rangeMax < bi.rangeMin {
   1677 			// The A and B cells don't overlap, and A precedes B.
   1678 			ai.seekTo(bi)
   1679 		} else if bi.rangeMax < ai.rangeMin {
   1680 			// The A and B cells don't overlap, and B precedes A.
   1681 			bi.seekTo(ai)
   1682 		} else {
   1683 			// One cell contains the other. Determine which cell is larger.
   1684 			abRelation := int64(ai.it.CellID().lsb() - bi.it.CellID().lsb())
   1685 			if abRelation > 0 {
   1686 				// A's index cell is larger.
   1687 				if ab.hasCrossingRelation(ai, bi) {
   1688 					return true
   1689 				}
   1690 			} else if abRelation < 0 {
   1691 				// B's index cell is larger.
   1692 				if ba.hasCrossingRelation(bi, ai) {
   1693 					return true
   1694 				}
   1695 			} else {
   1696 				// The A and B cells are the same. Since the two cells
   1697 				// have the same center point P, check whether P satisfies
   1698 				// the crossing targets.
   1699 				aClipped := ai.it.IndexCell().shapes[0]
   1700 				bClipped := bi.it.IndexCell().shapes[0]
   1701 				if containsCenterMatches(aClipped, ab.aCrossingTarget) &&
   1702 					containsCenterMatches(bClipped, ab.bCrossingTarget) {
   1703 					return true
   1704 				}
   1705 				// Otherwise test all the edge crossings directly.
   1706 				if aClipped.numEdges() > 0 && bClipped.numEdges() > 0 && ab.cellCrossesCell(aClipped, bClipped) {
   1707 					return true
   1708 				}
   1709 				ai.next()
   1710 				bi.next()
   1711 			}
   1712 		}
   1713 	}
   1714 	return false
   1715 }
   1716 
   1717 // containsRelation implements loopRelation for a contains operation. If
   1718 // A.ContainsPoint(P) == false && B.ContainsPoint(P) == true, it is equivalent
   1719 // to having an edge crossing (i.e., Contains returns false).
   1720 type containsRelation struct {
   1721 	foundSharedVertex bool
   1722 }
   1723 
   1724 func (c *containsRelation) aCrossingTarget() crossingTarget { return crossingTargetDontCross }
   1725 func (c *containsRelation) bCrossingTarget() crossingTarget { return crossingTargetCross }
   1726 func (c *containsRelation) wedgesCross(a0, ab1, a2, b0, b2 Point) bool {
   1727 	c.foundSharedVertex = true
   1728 	return !WedgeContains(a0, ab1, a2, b0, b2)
   1729 }
   1730 
   1731 // intersectsRelation implements loopRelation for an intersects operation. Given
   1732 // two loops, A and B, if A.ContainsPoint(P) == true && B.ContainsPoint(P) == true,
   1733 // it is equivalent to having an edge crossing (i.e., Intersects returns true).
   1734 type intersectsRelation struct {
   1735 	foundSharedVertex bool
   1736 }
   1737 
   1738 func (i *intersectsRelation) aCrossingTarget() crossingTarget { return crossingTargetCross }
   1739 func (i *intersectsRelation) bCrossingTarget() crossingTarget { return crossingTargetCross }
   1740 func (i *intersectsRelation) wedgesCross(a0, ab1, a2, b0, b2 Point) bool {
   1741 	i.foundSharedVertex = true
   1742 	return WedgeIntersects(a0, ab1, a2, b0, b2)
   1743 }
   1744 
   1745 // compareBoundaryRelation implements loopRelation for comparing boundaries.
   1746 //
   1747 // The compare boundary relation does not have a useful early-exit condition,
   1748 // so we return crossingTargetDontCare for both crossing targets.
   1749 //
   1750 // Aside: A possible early exit condition could be based on the following.
   1751 //   If A contains a point of both B and ~B, then A intersects Boundary(B).
   1752 //   If ~A contains a point of both B and ~B, then ~A intersects Boundary(B).
   1753 //   So if the intersections of {A, ~A} with {B, ~B} are all non-empty,
   1754 //   the return value is 0, i.e., Boundary(A) intersects Boundary(B).
   1755 // Unfortunately it isn't worth detecting this situation because by the
   1756 // time we have seen a point in all four intersection regions, we are also
   1757 // guaranteed to have seen at least one pair of crossing edges.
   1758 type compareBoundaryRelation struct {
   1759 	reverse           bool // True if the other loop should be reversed.
   1760 	foundSharedVertex bool // True if any wedge was processed.
   1761 	containsEdge      bool // True if any edge of the other loop is contained by this loop.
   1762 	excludesEdge      bool // True if any edge of the other loop is excluded by this loop.
   1763 }
   1764 
   1765 func newCompareBoundaryRelation(reverse bool) *compareBoundaryRelation {
   1766 	return &compareBoundaryRelation{reverse: reverse}
   1767 }
   1768 
   1769 func (c *compareBoundaryRelation) aCrossingTarget() crossingTarget { return crossingTargetDontCare }
   1770 func (c *compareBoundaryRelation) bCrossingTarget() crossingTarget { return crossingTargetDontCare }
   1771 func (c *compareBoundaryRelation) wedgesCross(a0, ab1, a2, b0, b2 Point) bool {
   1772 	// Because we don't care about the interior of the other, only its boundary,
   1773 	// it is sufficient to check whether this one contains the semiwedge (ab1, b2).
   1774 	c.foundSharedVertex = true
   1775 	if wedgeContainsSemiwedge(a0, ab1, a2, b2, c.reverse) {
   1776 		c.containsEdge = true
   1777 	} else {
   1778 		c.excludesEdge = true
   1779 	}
   1780 	return c.containsEdge && c.excludesEdge
   1781 }
   1782 
   1783 // wedgeContainsSemiwedge reports whether the wedge (a0, ab1, a2) contains the
   1784 // "semiwedge" defined as any non-empty open set of rays immediately CCW from
   1785 // the edge (ab1, b2). If reverse is true, then substitute clockwise for CCW;
   1786 // this simulates what would happen if the direction of the other loop was reversed.
   1787 func wedgeContainsSemiwedge(a0, ab1, a2, b2 Point, reverse bool) bool {
   1788 	if b2 == a0 || b2 == a2 {
   1789 		// We have a shared or reversed edge.
   1790 		return (b2 == a0) == reverse
   1791 	}
   1792 	return OrderedCCW(a0, a2, b2, ab1)
   1793 }
   1794 
   1795 // containsNonCrossingBoundary reports whether given two loops whose boundaries
   1796 // do not cross (see compareBoundary), if this loop contains the boundary of the
   1797 // other loop. If reverse is true, the boundary of the other loop is reversed
   1798 // first (which only affects the result when there are shared edges). This method
   1799 // is cheaper than compareBoundary because it does not test for edge intersections.
   1800 //
   1801 // This function requires that neither loop is empty, and that if the other is full,
   1802 // then reverse == false.
   1803 func (l *Loop) containsNonCrossingBoundary(other *Loop, reverseOther bool) bool {
   1804 	// The bounds must intersect for containment.
   1805 	if !l.bound.Intersects(other.bound) {
   1806 		return false
   1807 	}
   1808 
   1809 	// Full loops are handled as though the loop surrounded the entire sphere.
   1810 	if l.IsFull() {
   1811 		return true
   1812 	}
   1813 	if other.IsFull() {
   1814 		return false
   1815 	}
   1816 
   1817 	m, ok := l.findVertex(other.Vertex(0))
   1818 	if !ok {
   1819 		// Since the other loops vertex 0 is not shared, we can check if this contains it.
   1820 		return l.ContainsPoint(other.Vertex(0))
   1821 	}
   1822 	// Otherwise check whether the edge (b0, b1) is contained by this loop.
   1823 	return wedgeContainsSemiwedge(l.Vertex(m-1), l.Vertex(m), l.Vertex(m+1),
   1824 		other.Vertex(1), reverseOther)
   1825 }
   1826 
   1827 // TODO(roberts): Differences from the C++ version:
   1828 // DistanceToPoint
   1829 // DistanceToBoundary
   1830 // Project
   1831 // ProjectToBoundary
   1832 // BoundaryApproxEqual
   1833 // BoundaryNear