gtsocial-umbx

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

shapeindex.go (55623B)


      1 // Copyright 2016 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 	"math"
     19 	"sort"
     20 	"sync"
     21 	"sync/atomic"
     22 
     23 	"github.com/golang/geo/r1"
     24 	"github.com/golang/geo/r2"
     25 )
     26 
     27 // CellRelation describes the possible relationships between a target cell
     28 // and the cells of the ShapeIndex. If the target is an index cell or is
     29 // contained by an index cell, it is Indexed. If the target is subdivided
     30 // into one or more index cells, it is Subdivided. Otherwise it is Disjoint.
     31 type CellRelation int
     32 
     33 // The possible CellRelations for a ShapeIndex.
     34 const (
     35 	Indexed CellRelation = iota
     36 	Subdivided
     37 	Disjoint
     38 )
     39 
     40 const (
     41 	// cellPadding defines the total error when clipping an edge which comes
     42 	// from two sources:
     43 	// (1) Clipping the original spherical edge to a cube face (the face edge).
     44 	//     The maximum error in this step is faceClipErrorUVCoord.
     45 	// (2) Clipping the face edge to the u- or v-coordinate of a cell boundary.
     46 	//     The maximum error in this step is edgeClipErrorUVCoord.
     47 	// Finally, since we encounter the same errors when clipping query edges, we
     48 	// double the total error so that we only need to pad edges during indexing
     49 	// and not at query time.
     50 	cellPadding = 2.0 * (faceClipErrorUVCoord + edgeClipErrorUVCoord)
     51 
     52 	// cellSizeToLongEdgeRatio defines the cell size relative to the length of an
     53 	// edge at which it is first considered to be long. Long edges do not
     54 	// contribute toward the decision to subdivide a cell further. For example,
     55 	// a value of 2.0 means that the cell must be at least twice the size of the
     56 	// edge in order for that edge to be counted. There are two reasons for not
     57 	// counting long edges: (1) such edges typically need to be propagated to
     58 	// several children, which increases time and memory costs without much benefit,
     59 	// and (2) in pathological cases, many long edges close together could force
     60 	// subdivision to continue all the way to the leaf cell level.
     61 	cellSizeToLongEdgeRatio = 1.0
     62 )
     63 
     64 // clippedShape represents the part of a shape that intersects a Cell.
     65 // It consists of the set of edge IDs that intersect that cell and a boolean
     66 // indicating whether the center of the cell is inside the shape (for shapes
     67 // that have an interior).
     68 //
     69 // Note that the edges themselves are not clipped; we always use the original
     70 // edges for intersection tests so that the results will be the same as the
     71 // original shape.
     72 type clippedShape struct {
     73 	// shapeID is the index of the shape this clipped shape is a part of.
     74 	shapeID int32
     75 
     76 	// containsCenter indicates if the center of the CellID this shape has been
     77 	// clipped to falls inside this shape. This is false for shapes that do not
     78 	// have an interior.
     79 	containsCenter bool
     80 
     81 	// edges is the ordered set of ShapeIndex original edge IDs. Edges
     82 	// are stored in increasing order of edge ID.
     83 	edges []int
     84 }
     85 
     86 // newClippedShape returns a new clipped shape for the given shapeID and number of expected edges.
     87 func newClippedShape(id int32, numEdges int) *clippedShape {
     88 	return &clippedShape{
     89 		shapeID: id,
     90 		edges:   make([]int, numEdges),
     91 	}
     92 }
     93 
     94 // numEdges returns the number of edges that intersect the CellID of the Cell this was clipped to.
     95 func (c *clippedShape) numEdges() int {
     96 	return len(c.edges)
     97 }
     98 
     99 // containsEdge reports if this clipped shape contains the given edge ID.
    100 func (c *clippedShape) containsEdge(id int) bool {
    101 	// Linear search is fast because the number of edges per shape is typically
    102 	// very small (less than 10).
    103 	for _, e := range c.edges {
    104 		if e == id {
    105 			return true
    106 		}
    107 	}
    108 	return false
    109 }
    110 
    111 // ShapeIndexCell stores the index contents for a particular CellID.
    112 type ShapeIndexCell struct {
    113 	shapes []*clippedShape
    114 }
    115 
    116 // NewShapeIndexCell creates a new cell that is sized to hold the given number of shapes.
    117 func NewShapeIndexCell(numShapes int) *ShapeIndexCell {
    118 	return &ShapeIndexCell{
    119 		shapes: make([]*clippedShape, numShapes),
    120 	}
    121 }
    122 
    123 // numEdges reports the total number of edges in all clipped shapes in this cell.
    124 func (s *ShapeIndexCell) numEdges() int {
    125 	var e int
    126 	for _, cs := range s.shapes {
    127 		e += cs.numEdges()
    128 	}
    129 	return e
    130 }
    131 
    132 // add adds the given clipped shape to this index cell.
    133 func (s *ShapeIndexCell) add(c *clippedShape) {
    134 	// C++ uses a set, so it's ordered and unique. We don't currently catch
    135 	// the case when a duplicate value is added.
    136 	s.shapes = append(s.shapes, c)
    137 }
    138 
    139 // findByShapeID returns the clipped shape that contains the given shapeID,
    140 // or nil if none of the clipped shapes contain it.
    141 func (s *ShapeIndexCell) findByShapeID(shapeID int32) *clippedShape {
    142 	// Linear search is fine because the number of shapes per cell is typically
    143 	// very small (most often 1), and is large only for pathological inputs
    144 	// (e.g. very deeply nested loops).
    145 	for _, clipped := range s.shapes {
    146 		if clipped.shapeID == shapeID {
    147 			return clipped
    148 		}
    149 	}
    150 	return nil
    151 }
    152 
    153 // faceEdge and clippedEdge store temporary edge data while the index is being
    154 // updated.
    155 //
    156 // While it would be possible to combine all the edge information into one
    157 // structure, there are two good reasons for separating it:
    158 //
    159 //  - Memory usage. Separating the two means that we only need to
    160 //    store one copy of the per-face data no matter how many times an edge is
    161 //    subdivided, and it also lets us delay computing bounding boxes until
    162 //    they are needed for processing each face (when the dataset spans
    163 //    multiple faces).
    164 //
    165 //  - Performance. UpdateEdges is significantly faster on large polygons when
    166 //    the data is separated, because it often only needs to access the data in
    167 //    clippedEdge and this data is cached more successfully.
    168 
    169 // faceEdge represents an edge that has been projected onto a given face,
    170 type faceEdge struct {
    171 	shapeID     int32    // The ID of shape that this edge belongs to
    172 	edgeID      int      // Edge ID within that shape
    173 	maxLevel    int      // Not desirable to subdivide this edge beyond this level
    174 	hasInterior bool     // Belongs to a shape that has a dimension of 2
    175 	a, b        r2.Point // The edge endpoints, clipped to a given face
    176 	edge        Edge     // The original edge.
    177 }
    178 
    179 // clippedEdge represents the portion of that edge that has been clipped to a given Cell.
    180 type clippedEdge struct {
    181 	faceEdge *faceEdge // The original unclipped edge
    182 	bound    r2.Rect   // Bounding box for the clipped portion
    183 }
    184 
    185 // ShapeIndexIteratorPos defines the set of possible iterator starting positions. By
    186 // default iterators are unpositioned, since this avoids an extra seek in this
    187 // situation where one of the seek methods (such as Locate) is immediately called.
    188 type ShapeIndexIteratorPos int
    189 
    190 const (
    191 	// IteratorBegin specifies the iterator should be positioned at the beginning of the index.
    192 	IteratorBegin ShapeIndexIteratorPos = iota
    193 	// IteratorEnd specifies the iterator should be positioned at the end of the index.
    194 	IteratorEnd
    195 )
    196 
    197 // ShapeIndexIterator is an iterator that provides low-level access to
    198 // the cells of the index. Cells are returned in increasing order of CellID.
    199 //
    200 //   for it := index.Iterator(); !it.Done(); it.Next() {
    201 //     fmt.Print(it.CellID())
    202 //   }
    203 //
    204 type ShapeIndexIterator struct {
    205 	index    *ShapeIndex
    206 	position int
    207 	id       CellID
    208 	cell     *ShapeIndexCell
    209 }
    210 
    211 // NewShapeIndexIterator creates a new iterator for the given index. If a starting
    212 // position is specified, the iterator is positioned at the given spot.
    213 func NewShapeIndexIterator(index *ShapeIndex, pos ...ShapeIndexIteratorPos) *ShapeIndexIterator {
    214 	s := &ShapeIndexIterator{
    215 		index: index,
    216 	}
    217 
    218 	if len(pos) > 0 {
    219 		if len(pos) > 1 {
    220 			panic("too many ShapeIndexIteratorPos arguments")
    221 		}
    222 		switch pos[0] {
    223 		case IteratorBegin:
    224 			s.Begin()
    225 		case IteratorEnd:
    226 			s.End()
    227 		default:
    228 			panic("unknown ShapeIndexIteratorPos value")
    229 		}
    230 	}
    231 
    232 	return s
    233 }
    234 
    235 func (s *ShapeIndexIterator) clone() *ShapeIndexIterator {
    236 	return &ShapeIndexIterator{
    237 		index:    s.index,
    238 		position: s.position,
    239 		id:       s.id,
    240 		cell:     s.cell,
    241 	}
    242 }
    243 
    244 // CellID returns the CellID of the current index cell.
    245 // If s.Done() is true, a value larger than any valid CellID is returned.
    246 func (s *ShapeIndexIterator) CellID() CellID {
    247 	return s.id
    248 }
    249 
    250 // IndexCell returns the current index cell.
    251 func (s *ShapeIndexIterator) IndexCell() *ShapeIndexCell {
    252 	// TODO(roberts): C++ has this call a virtual method to allow subclasses
    253 	// of ShapeIndexIterator to do other work before returning the cell. Do
    254 	// we need such a thing?
    255 	return s.cell
    256 }
    257 
    258 // Center returns the Point at the center of the current position of the iterator.
    259 func (s *ShapeIndexIterator) Center() Point {
    260 	return s.CellID().Point()
    261 }
    262 
    263 // Begin positions the iterator at the beginning of the index.
    264 func (s *ShapeIndexIterator) Begin() {
    265 	if !s.index.IsFresh() {
    266 		s.index.maybeApplyUpdates()
    267 	}
    268 	s.position = 0
    269 	s.refresh()
    270 }
    271 
    272 // Next positions the iterator at the next index cell.
    273 func (s *ShapeIndexIterator) Next() {
    274 	s.position++
    275 	s.refresh()
    276 }
    277 
    278 // Prev advances the iterator to the previous cell in the index and returns true to
    279 // indicate it was not yet at the beginning of the index. If the iterator is at the
    280 // first cell the call does nothing and returns false.
    281 func (s *ShapeIndexIterator) Prev() bool {
    282 	if s.position <= 0 {
    283 		return false
    284 	}
    285 
    286 	s.position--
    287 	s.refresh()
    288 	return true
    289 }
    290 
    291 // End positions the iterator at the end of the index.
    292 func (s *ShapeIndexIterator) End() {
    293 	s.position = len(s.index.cells)
    294 	s.refresh()
    295 }
    296 
    297 // Done reports if the iterator is positioned at or after the last index cell.
    298 func (s *ShapeIndexIterator) Done() bool {
    299 	return s.id == SentinelCellID
    300 }
    301 
    302 // refresh updates the stored internal iterator values.
    303 func (s *ShapeIndexIterator) refresh() {
    304 	if s.position < len(s.index.cells) {
    305 		s.id = s.index.cells[s.position]
    306 		s.cell = s.index.cellMap[s.CellID()]
    307 	} else {
    308 		s.id = SentinelCellID
    309 		s.cell = nil
    310 	}
    311 }
    312 
    313 // seek positions the iterator at the first cell whose ID >= target, or at the
    314 // end of the index if no such cell exists.
    315 func (s *ShapeIndexIterator) seek(target CellID) {
    316 	s.position = sort.Search(len(s.index.cells), func(i int) bool {
    317 		return s.index.cells[i] >= target
    318 	})
    319 	s.refresh()
    320 }
    321 
    322 // LocatePoint positions the iterator at the cell that contains the given Point.
    323 // If no such cell exists, the iterator position is unspecified, and false is returned.
    324 // The cell at the matched position is guaranteed to contain all edges that might
    325 // intersect the line segment between target and the cell's center.
    326 func (s *ShapeIndexIterator) LocatePoint(p Point) bool {
    327 	// Let I = cellMap.LowerBound(T), where T is the leaf cell containing
    328 	// point P. Then if T is contained by an index cell, then the
    329 	// containing cell is either I or I'. We test for containment by comparing
    330 	// the ranges of leaf cells spanned by T, I, and I'.
    331 	target := cellIDFromPoint(p)
    332 	s.seek(target)
    333 	if !s.Done() && s.CellID().RangeMin() <= target {
    334 		return true
    335 	}
    336 
    337 	if s.Prev() && s.CellID().RangeMax() >= target {
    338 		return true
    339 	}
    340 	return false
    341 }
    342 
    343 // LocateCellID attempts to position the iterator at the first matching index cell
    344 // in the index that has some relation to the given CellID. Let T be the target CellID.
    345 // If T is contained by (or equal to) some index cell I, then the iterator is positioned
    346 // at I and returns Indexed. Otherwise if T contains one or more (smaller) index cells,
    347 // then the iterator is positioned at the first such cell I and return Subdivided.
    348 // Otherwise Disjoint is returned and the iterator position is undefined.
    349 func (s *ShapeIndexIterator) LocateCellID(target CellID) CellRelation {
    350 	// Let T be the target, let I = cellMap.LowerBound(T.RangeMin()), and
    351 	// let I' be the predecessor of I. If T contains any index cells, then T
    352 	// contains I. Similarly, if T is contained by an index cell, then the
    353 	// containing cell is either I or I'. We test for containment by comparing
    354 	// the ranges of leaf cells spanned by T, I, and I'.
    355 	s.seek(target.RangeMin())
    356 	if !s.Done() {
    357 		if s.CellID() >= target && s.CellID().RangeMin() <= target {
    358 			return Indexed
    359 		}
    360 		if s.CellID() <= target.RangeMax() {
    361 			return Subdivided
    362 		}
    363 	}
    364 	if s.Prev() && s.CellID().RangeMax() >= target {
    365 		return Indexed
    366 	}
    367 	return Disjoint
    368 }
    369 
    370 // tracker keeps track of which shapes in a given set contain a particular point
    371 // (the focus). It provides an efficient way to move the focus from one point
    372 // to another and incrementally update the set of shapes which contain it. We use
    373 // this to compute which shapes contain the center of every CellID in the index,
    374 // by advancing the focus from one cell center to the next.
    375 //
    376 // Initially the focus is at the start of the CellID space-filling curve. We then
    377 // visit all the cells that are being added to the ShapeIndex in increasing order
    378 // of CellID. For each cell, we draw two edges: one from the entry vertex to the
    379 // center, and another from the center to the exit vertex (where entry and exit
    380 // refer to the points where the space-filling curve enters and exits the cell).
    381 // By counting edge crossings we can incrementally compute which shapes contain
    382 // the cell center. Note that the same set of shapes will always contain the exit
    383 // point of one cell and the entry point of the next cell in the index, because
    384 // either (a) these two points are actually the same, or (b) the intervening
    385 // cells in CellID order are all empty, and therefore there are no edge crossings
    386 // if we follow this path from one cell to the other.
    387 //
    388 // In C++, this is S2ShapeIndex::InteriorTracker.
    389 type tracker struct {
    390 	isActive   bool
    391 	a          Point
    392 	b          Point
    393 	nextCellID CellID
    394 	crosser    *EdgeCrosser
    395 	shapeIDs   []int32
    396 
    397 	// Shape ids saved by saveAndClearStateBefore. The state is never saved
    398 	// recursively so we don't need to worry about maintaining a stack.
    399 	savedIDs []int32
    400 }
    401 
    402 // newTracker returns a new tracker with the appropriate defaults.
    403 func newTracker() *tracker {
    404 	// As shapes are added, we compute which ones contain the start of the
    405 	// CellID space-filling curve by drawing an edge from OriginPoint to this
    406 	// point and counting how many shape edges cross this edge.
    407 	t := &tracker{
    408 		isActive:   false,
    409 		b:          trackerOrigin(),
    410 		nextCellID: CellIDFromFace(0).ChildBeginAtLevel(maxLevel),
    411 	}
    412 	t.drawTo(Point{faceUVToXYZ(0, -1, -1).Normalize()}) // CellID curve start
    413 
    414 	return t
    415 }
    416 
    417 // trackerOrigin returns the initial focus point when the tracker is created
    418 // (corresponding to the start of the CellID space-filling curve).
    419 func trackerOrigin() Point {
    420 	// The start of the S2CellId space-filling curve.
    421 	return Point{faceUVToXYZ(0, -1, -1).Normalize()}
    422 }
    423 
    424 // focus returns the current focus point of the tracker.
    425 func (t *tracker) focus() Point { return t.b }
    426 
    427 // addShape adds a shape whose interior should be tracked. containsOrigin indicates
    428 // whether the current focus point is inside the shape. Alternatively, if
    429 // the focus point is in the process of being moved (via moveTo/drawTo), you
    430 // can also specify containsOrigin at the old focus point and call testEdge
    431 // for every edge of the shape that might cross the current drawTo line.
    432 // This updates the state to correspond to the new focus point.
    433 //
    434 // This requires shape.HasInterior
    435 func (t *tracker) addShape(shapeID int32, containsFocus bool) {
    436 	t.isActive = true
    437 	if containsFocus {
    438 		t.toggleShape(shapeID)
    439 	}
    440 }
    441 
    442 // moveTo moves the focus of the tracker to the given point. This method should
    443 // only be used when it is known that there are no edge crossings between the old
    444 // and new focus locations; otherwise use drawTo.
    445 func (t *tracker) moveTo(b Point) { t.b = b }
    446 
    447 // drawTo moves the focus of the tracker to the given point. After this method is
    448 // called, testEdge should be called with all edges that may cross the line
    449 // segment between the old and new focus locations.
    450 func (t *tracker) drawTo(b Point) {
    451 	t.a = t.b
    452 	t.b = b
    453 	// TODO: the edge crosser may need an in-place Init method if this gets expensive
    454 	t.crosser = NewEdgeCrosser(t.a, t.b)
    455 }
    456 
    457 // testEdge checks if the given edge crosses the current edge, and if so, then
    458 // toggle the state of the given shapeID.
    459 // This requires shape to have an interior.
    460 func (t *tracker) testEdge(shapeID int32, edge Edge) {
    461 	if t.crosser.EdgeOrVertexCrossing(edge.V0, edge.V1) {
    462 		t.toggleShape(shapeID)
    463 	}
    464 }
    465 
    466 // setNextCellID is used to indicate that the last argument to moveTo or drawTo
    467 // was the entry vertex of the given CellID, i.e. the tracker is positioned at the
    468 // start of this cell. By using this method together with atCellID, the caller
    469 // can avoid calling moveTo in cases where the exit vertex of the previous cell
    470 // is the same as the entry vertex of the current cell.
    471 func (t *tracker) setNextCellID(nextCellID CellID) {
    472 	t.nextCellID = nextCellID.RangeMin()
    473 }
    474 
    475 // atCellID reports if the focus is already at the entry vertex of the given
    476 // CellID (provided that the caller calls setNextCellID as each cell is processed).
    477 func (t *tracker) atCellID(cellid CellID) bool {
    478 	return cellid.RangeMin() == t.nextCellID
    479 }
    480 
    481 // toggleShape adds or removes the given shapeID from the set of IDs it is tracking.
    482 func (t *tracker) toggleShape(shapeID int32) {
    483 	// Most shapeIDs slices are small, so special case the common steps.
    484 
    485 	// If there is nothing here, add it.
    486 	if len(t.shapeIDs) == 0 {
    487 		t.shapeIDs = append(t.shapeIDs, shapeID)
    488 		return
    489 	}
    490 
    491 	// If it's the first element, drop it from the slice.
    492 	if t.shapeIDs[0] == shapeID {
    493 		t.shapeIDs = t.shapeIDs[1:]
    494 		return
    495 	}
    496 
    497 	for i, s := range t.shapeIDs {
    498 		if s < shapeID {
    499 			continue
    500 		}
    501 
    502 		// If it's in the set, cut it out.
    503 		if s == shapeID {
    504 			copy(t.shapeIDs[i:], t.shapeIDs[i+1:]) // overwrite the ith element
    505 			t.shapeIDs = t.shapeIDs[:len(t.shapeIDs)-1]
    506 			return
    507 		}
    508 
    509 		// We've got to a point in the slice where we should be inserted.
    510 		// (the given shapeID is now less than the current positions id.)
    511 		t.shapeIDs = append(t.shapeIDs[0:i],
    512 			append([]int32{shapeID}, t.shapeIDs[i:len(t.shapeIDs)]...)...)
    513 		return
    514 	}
    515 
    516 	// We got to the end and didn't find it, so add it to the list.
    517 	t.shapeIDs = append(t.shapeIDs, shapeID)
    518 }
    519 
    520 // saveAndClearStateBefore makes an internal copy of the state for shape ids below
    521 // the given limit, and then clear the state for those shapes. This is used during
    522 // incremental updates to track the state of added and removed shapes separately.
    523 func (t *tracker) saveAndClearStateBefore(limitShapeID int32) {
    524 	limit := t.lowerBound(limitShapeID)
    525 	t.savedIDs = append([]int32(nil), t.shapeIDs[:limit]...)
    526 	t.shapeIDs = t.shapeIDs[limit:]
    527 }
    528 
    529 // restoreStateBefore restores the state previously saved by saveAndClearStateBefore.
    530 // This only affects the state for shapeIDs below "limitShapeID".
    531 func (t *tracker) restoreStateBefore(limitShapeID int32) {
    532 	limit := t.lowerBound(limitShapeID)
    533 	t.shapeIDs = append(append([]int32(nil), t.savedIDs...), t.shapeIDs[limit:]...)
    534 	t.savedIDs = nil
    535 }
    536 
    537 // lowerBound returns the shapeID of the first entry x where x >= shapeID.
    538 func (t *tracker) lowerBound(shapeID int32) int32 {
    539 	panic("not implemented")
    540 }
    541 
    542 // removedShape represents a set of edges from the given shape that is queued for removal.
    543 type removedShape struct {
    544 	shapeID               int32
    545 	hasInterior           bool
    546 	containsTrackerOrigin bool
    547 	edges                 []Edge
    548 }
    549 
    550 // There are three basic states the index can be in.
    551 const (
    552 	stale    int32 = iota // There are pending updates.
    553 	updating              // Updates are currently being applied.
    554 	fresh                 // There are no pending updates.
    555 )
    556 
    557 // ShapeIndex indexes a set of Shapes, where a Shape is some collection of edges
    558 // that optionally defines an interior. It can be used to represent a set of
    559 // points, a set of polylines, or a set of polygons. For Shapes that have
    560 // interiors, the index makes it very fast to determine which Shape(s) contain
    561 // a given point or region.
    562 //
    563 // The index can be updated incrementally by adding or removing shapes. It is
    564 // designed to handle up to hundreds of millions of edges. All data structures
    565 // are designed to be small, so the index is compact; generally it is smaller
    566 // than the underlying data being indexed. The index is also fast to construct.
    567 //
    568 // Polygon, Loop, and Polyline implement Shape which allows these objects to
    569 // be indexed easily. You can find useful query methods in CrossingEdgeQuery
    570 // and ClosestEdgeQuery (Not yet implemented in Go).
    571 //
    572 // Example showing how to build an index of Polylines:
    573 //
    574 //   index := NewShapeIndex()
    575 //   for _, polyline := range polylines {
    576 //       index.Add(polyline);
    577 //   }
    578 //   // Now you can use a CrossingEdgeQuery or ClosestEdgeQuery here.
    579 //
    580 type ShapeIndex struct {
    581 	// shapes is a map of shape ID to shape.
    582 	shapes map[int32]Shape
    583 
    584 	// The maximum number of edges per cell.
    585 	// TODO(roberts): Update the comments when the usage of this is implemented.
    586 	maxEdgesPerCell int
    587 
    588 	// nextID tracks the next ID to hand out. IDs are not reused when shapes
    589 	// are removed from the index.
    590 	nextID int32
    591 
    592 	// cellMap is a map from CellID to the set of clipped shapes that intersect that
    593 	// cell. The cell IDs cover a set of non-overlapping regions on the sphere.
    594 	// In C++, this is a BTree, so the cells are ordered naturally by the data structure.
    595 	cellMap map[CellID]*ShapeIndexCell
    596 	// Track the ordered list of cell IDs.
    597 	cells []CellID
    598 
    599 	// The current status of the index; accessed atomically.
    600 	status int32
    601 
    602 	// Additions and removals are queued and processed on the first subsequent
    603 	// query. There are several reasons to do this:
    604 	//
    605 	//  - It is significantly more efficient to process updates in batches if
    606 	//    the amount of entities added grows.
    607 	//  - Often the index will never be queried, in which case we can save both
    608 	//    the time and memory required to build it. Examples:
    609 	//     + Loops that are created simply to pass to an Polygon. (We don't
    610 	//       need the Loop index, because Polygon builds its own index.)
    611 	//     + Applications that load a database of geometry and then query only
    612 	//       a small fraction of it.
    613 	//
    614 	// The main drawback is that we need to go to some extra work to ensure that
    615 	// some methods are still thread-safe. Note that the goal is *not* to
    616 	// make this thread-safe in general, but simply to hide the fact that
    617 	// we defer some of the indexing work until query time.
    618 	//
    619 	// This mutex protects all of following fields in the index.
    620 	mu sync.RWMutex
    621 
    622 	// pendingAdditionsPos is the index of the first entry that has not been processed
    623 	// via applyUpdatesInternal.
    624 	pendingAdditionsPos int32
    625 
    626 	// The set of shapes that have been queued for removal but not processed yet by
    627 	// applyUpdatesInternal.
    628 	pendingRemovals []*removedShape
    629 }
    630 
    631 // NewShapeIndex creates a new ShapeIndex.
    632 func NewShapeIndex() *ShapeIndex {
    633 	return &ShapeIndex{
    634 		maxEdgesPerCell: 10,
    635 		shapes:          make(map[int32]Shape),
    636 		cellMap:         make(map[CellID]*ShapeIndexCell),
    637 		cells:           nil,
    638 		status:          fresh,
    639 	}
    640 }
    641 
    642 // Iterator returns an iterator for this index.
    643 func (s *ShapeIndex) Iterator() *ShapeIndexIterator {
    644 	s.maybeApplyUpdates()
    645 	return NewShapeIndexIterator(s, IteratorBegin)
    646 }
    647 
    648 // Begin positions the iterator at the first cell in the index.
    649 func (s *ShapeIndex) Begin() *ShapeIndexIterator {
    650 	s.maybeApplyUpdates()
    651 	return NewShapeIndexIterator(s, IteratorBegin)
    652 }
    653 
    654 // End positions the iterator at the last cell in the index.
    655 func (s *ShapeIndex) End() *ShapeIndexIterator {
    656 	// TODO(roberts): It's possible that updates could happen to the index between
    657 	// the time this is called and the time the iterators position is used and this
    658 	// will be invalid or not the end. For now, things will be undefined if this
    659 	// happens. See about referencing the IsFresh to guard for this in the future.
    660 	s.maybeApplyUpdates()
    661 	return NewShapeIndexIterator(s, IteratorEnd)
    662 }
    663 
    664 // Len reports the number of Shapes in this index.
    665 func (s *ShapeIndex) Len() int {
    666 	return len(s.shapes)
    667 }
    668 
    669 // Reset resets the index to its original state.
    670 func (s *ShapeIndex) Reset() {
    671 	s.shapes = make(map[int32]Shape)
    672 	s.nextID = 0
    673 	s.cellMap = make(map[CellID]*ShapeIndexCell)
    674 	s.cells = nil
    675 	atomic.StoreInt32(&s.status, fresh)
    676 }
    677 
    678 // NumEdges returns the number of edges in this index.
    679 func (s *ShapeIndex) NumEdges() int {
    680 	numEdges := 0
    681 	for _, shape := range s.shapes {
    682 		numEdges += shape.NumEdges()
    683 	}
    684 	return numEdges
    685 }
    686 
    687 // NumEdgesUpTo returns the number of edges in the given index, up to the given
    688 // limit. If the limit is encountered, the current running total is returned,
    689 // which may be more than the limit.
    690 func (s *ShapeIndex) NumEdgesUpTo(limit int) int {
    691 	var numEdges int
    692 	// We choose to iterate over the shapes in order to match the counting
    693 	// up behavior in C++ and for test compatibility instead of using a
    694 	// more idiomatic range over the shape map.
    695 	for i := int32(0); i <= s.nextID; i++ {
    696 		s := s.Shape(i)
    697 		if s == nil {
    698 			continue
    699 		}
    700 		numEdges += s.NumEdges()
    701 		if numEdges >= limit {
    702 			break
    703 		}
    704 	}
    705 
    706 	return numEdges
    707 }
    708 
    709 // Shape returns the shape with the given ID, or nil if the shape has been removed from the index.
    710 func (s *ShapeIndex) Shape(id int32) Shape { return s.shapes[id] }
    711 
    712 // idForShape returns the id of the given shape in this index, or -1 if it is
    713 // not in the index.
    714 //
    715 // TODO(roberts): Need to figure out an appropriate way to expose this on a Shape.
    716 // C++ allows a given S2 type (Loop, Polygon, etc) to be part of multiple indexes.
    717 // By having each type extend S2Shape which has an id element, they all inherit their
    718 // own id field rather than having to track it themselves.
    719 func (s *ShapeIndex) idForShape(shape Shape) int32 {
    720 	for k, v := range s.shapes {
    721 		if v == shape {
    722 			return k
    723 		}
    724 	}
    725 	return -1
    726 }
    727 
    728 // Add adds the given shape to the index and returns the assigned ID..
    729 func (s *ShapeIndex) Add(shape Shape) int32 {
    730 	s.shapes[s.nextID] = shape
    731 	s.nextID++
    732 	atomic.StoreInt32(&s.status, stale)
    733 	return s.nextID - 1
    734 }
    735 
    736 // Remove removes the given shape from the index.
    737 func (s *ShapeIndex) Remove(shape Shape) {
    738 	// The index updates itself lazily because it is much more efficient to
    739 	// process additions and removals in batches.
    740 	id := s.idForShape(shape)
    741 
    742 	// If the shape wasn't found, it's already been removed or was not in the index.
    743 	if s.shapes[id] == nil {
    744 		return
    745 	}
    746 
    747 	// Remove the shape from the shapes map.
    748 	delete(s.shapes, id)
    749 
    750 	// We are removing a shape that has not yet been added to the index,
    751 	// so there is nothing else to do.
    752 	if id >= s.pendingAdditionsPos {
    753 		return
    754 	}
    755 
    756 	numEdges := shape.NumEdges()
    757 	removed := &removedShape{
    758 		shapeID:               id,
    759 		hasInterior:           shape.Dimension() == 2,
    760 		containsTrackerOrigin: shape.ReferencePoint().Contained,
    761 		edges:                 make([]Edge, numEdges),
    762 	}
    763 
    764 	for e := 0; e < numEdges; e++ {
    765 		removed.edges[e] = shape.Edge(e)
    766 	}
    767 
    768 	s.pendingRemovals = append(s.pendingRemovals, removed)
    769 	atomic.StoreInt32(&s.status, stale)
    770 }
    771 
    772 // Build triggers the update of the index. Calls to Add and Release are normally
    773 // queued and processed on the first subsequent query. This has many advantages,
    774 // the most important of which is that sometimes there *is* no subsequent
    775 // query, which lets us avoid building the index completely.
    776 //
    777 // This method forces any pending updates to be applied immediately.
    778 func (s *ShapeIndex) Build() {
    779 	s.maybeApplyUpdates()
    780 }
    781 
    782 // IsFresh reports if there are no pending updates that need to be applied.
    783 // This can be useful to avoid building the index unnecessarily, or for
    784 // choosing between two different algorithms depending on whether the index
    785 // is available.
    786 //
    787 // The returned index status may be slightly out of date if the index was
    788 // built in a different thread. This is fine for the intended use (as an
    789 // efficiency hint), but it should not be used by internal methods.
    790 func (s *ShapeIndex) IsFresh() bool {
    791 	return atomic.LoadInt32(&s.status) == fresh
    792 }
    793 
    794 // isFirstUpdate reports if this is the first update to the index.
    795 func (s *ShapeIndex) isFirstUpdate() bool {
    796 	// Note that it is not sufficient to check whether cellMap is empty, since
    797 	// entries are added to it during the update process.
    798 	return s.pendingAdditionsPos == 0
    799 }
    800 
    801 // isShapeBeingRemoved reports if the shape with the given ID is currently slated for removal.
    802 func (s *ShapeIndex) isShapeBeingRemoved(shapeID int32) bool {
    803 	// All shape ids being removed fall below the index position of shapes being added.
    804 	return shapeID < s.pendingAdditionsPos
    805 }
    806 
    807 // maybeApplyUpdates checks if the index pieces have changed, and if so, applies pending updates.
    808 func (s *ShapeIndex) maybeApplyUpdates() {
    809 	// TODO(roberts): To avoid acquiring and releasing the mutex on every
    810 	// query, we should use atomic operations when testing whether the status
    811 	// is fresh and when updating the status to be fresh. This guarantees
    812 	// that any thread that sees a status of fresh will also see the
    813 	// corresponding index updates.
    814 	if atomic.LoadInt32(&s.status) != fresh {
    815 		s.mu.Lock()
    816 		s.applyUpdatesInternal()
    817 		atomic.StoreInt32(&s.status, fresh)
    818 		s.mu.Unlock()
    819 	}
    820 }
    821 
    822 // applyUpdatesInternal does the actual work of updating the index by applying all
    823 // pending additions and removals. It does *not* update the indexes status.
    824 func (s *ShapeIndex) applyUpdatesInternal() {
    825 	// TODO(roberts): Building the index can use up to 20x as much memory per
    826 	// edge as the final index memory size. If this causes issues, add in
    827 	// batched updating to limit the amount of items per batch to a
    828 	// configurable memory footprint overhead.
    829 	t := newTracker()
    830 
    831 	// allEdges maps a Face to a collection of faceEdges.
    832 	allEdges := make([][]faceEdge, 6)
    833 
    834 	for _, p := range s.pendingRemovals {
    835 		s.removeShapeInternal(p, allEdges, t)
    836 	}
    837 
    838 	for id := s.pendingAdditionsPos; id < int32(len(s.shapes)); id++ {
    839 		s.addShapeInternal(id, allEdges, t)
    840 	}
    841 
    842 	for face := 0; face < 6; face++ {
    843 		s.updateFaceEdges(face, allEdges[face], t)
    844 	}
    845 
    846 	s.pendingRemovals = s.pendingRemovals[:0]
    847 	s.pendingAdditionsPos = int32(len(s.shapes))
    848 	// It is the caller's responsibility to update the index status.
    849 }
    850 
    851 // addShapeInternal clips all edges of the given shape to the six cube faces,
    852 // adds the clipped edges to the set of allEdges, and starts tracking its
    853 // interior if necessary.
    854 func (s *ShapeIndex) addShapeInternal(shapeID int32, allEdges [][]faceEdge, t *tracker) {
    855 	shape, ok := s.shapes[shapeID]
    856 	if !ok {
    857 		// This shape has already been removed.
    858 		return
    859 	}
    860 
    861 	faceEdge := faceEdge{
    862 		shapeID:     shapeID,
    863 		hasInterior: shape.Dimension() == 2,
    864 	}
    865 
    866 	if faceEdge.hasInterior {
    867 		t.addShape(shapeID, containsBruteForce(shape, t.focus()))
    868 	}
    869 
    870 	numEdges := shape.NumEdges()
    871 	for e := 0; e < numEdges; e++ {
    872 		edge := shape.Edge(e)
    873 
    874 		faceEdge.edgeID = e
    875 		faceEdge.edge = edge
    876 		faceEdge.maxLevel = maxLevelForEdge(edge)
    877 		s.addFaceEdge(faceEdge, allEdges)
    878 	}
    879 }
    880 
    881 // addFaceEdge adds the given faceEdge into the collection of all edges.
    882 func (s *ShapeIndex) addFaceEdge(fe faceEdge, allEdges [][]faceEdge) {
    883 	aFace := face(fe.edge.V0.Vector)
    884 	// See if both endpoints are on the same face, and are far enough from
    885 	// the edge of the face that they don't intersect any (padded) adjacent face.
    886 	if aFace == face(fe.edge.V1.Vector) {
    887 		x, y := validFaceXYZToUV(aFace, fe.edge.V0.Vector)
    888 		fe.a = r2.Point{x, y}
    889 		x, y = validFaceXYZToUV(aFace, fe.edge.V1.Vector)
    890 		fe.b = r2.Point{x, y}
    891 
    892 		maxUV := 1 - cellPadding
    893 		if math.Abs(fe.a.X) <= maxUV && math.Abs(fe.a.Y) <= maxUV &&
    894 			math.Abs(fe.b.X) <= maxUV && math.Abs(fe.b.Y) <= maxUV {
    895 			allEdges[aFace] = append(allEdges[aFace], fe)
    896 			return
    897 		}
    898 	}
    899 
    900 	// Otherwise, we simply clip the edge to all six faces.
    901 	for face := 0; face < 6; face++ {
    902 		if aClip, bClip, intersects := ClipToPaddedFace(fe.edge.V0, fe.edge.V1, face, cellPadding); intersects {
    903 			fe.a = aClip
    904 			fe.b = bClip
    905 			allEdges[face] = append(allEdges[face], fe)
    906 		}
    907 	}
    908 }
    909 
    910 // updateFaceEdges adds or removes the various edges from the index.
    911 // An edge is added if shapes[id] is not nil, and removed otherwise.
    912 func (s *ShapeIndex) updateFaceEdges(face int, faceEdges []faceEdge, t *tracker) {
    913 	numEdges := len(faceEdges)
    914 	if numEdges == 0 && len(t.shapeIDs) == 0 {
    915 		return
    916 	}
    917 
    918 	// Create the initial clippedEdge for each faceEdge. Additional clipped
    919 	// edges are created when edges are split between child cells. We create
    920 	// two arrays, one containing the edge data and another containing pointers
    921 	// to those edges, so that during the recursion we only need to copy
    922 	// pointers in order to propagate an edge to the correct child.
    923 	clippedEdges := make([]*clippedEdge, numEdges)
    924 	bound := r2.EmptyRect()
    925 	for e := 0; e < numEdges; e++ {
    926 		clipped := &clippedEdge{
    927 			faceEdge: &faceEdges[e],
    928 		}
    929 		clipped.bound = r2.RectFromPoints(faceEdges[e].a, faceEdges[e].b)
    930 		clippedEdges[e] = clipped
    931 		bound = bound.AddRect(clipped.bound)
    932 	}
    933 
    934 	// Construct the initial face cell containing all the edges, and then update
    935 	// all the edges in the index recursively.
    936 	faceID := CellIDFromFace(face)
    937 	pcell := PaddedCellFromCellID(faceID, cellPadding)
    938 
    939 	disjointFromIndex := s.isFirstUpdate()
    940 	if numEdges > 0 {
    941 		shrunkID := s.shrinkToFit(pcell, bound)
    942 		if shrunkID != pcell.id {
    943 			// All the edges are contained by some descendant of the face cell. We
    944 			// can save a lot of work by starting directly with that cell, but if we
    945 			// are in the interior of at least one shape then we need to create
    946 			// index entries for the cells we are skipping over.
    947 			s.skipCellRange(faceID.RangeMin(), shrunkID.RangeMin(), t, disjointFromIndex)
    948 			pcell = PaddedCellFromCellID(shrunkID, cellPadding)
    949 			s.updateEdges(pcell, clippedEdges, t, disjointFromIndex)
    950 			s.skipCellRange(shrunkID.RangeMax().Next(), faceID.RangeMax().Next(), t, disjointFromIndex)
    951 			return
    952 		}
    953 	}
    954 
    955 	// Otherwise (no edges, or no shrinking is possible), subdivide normally.
    956 	s.updateEdges(pcell, clippedEdges, t, disjointFromIndex)
    957 }
    958 
    959 // shrinkToFit shrinks the PaddedCell to fit within the given bounds.
    960 func (s *ShapeIndex) shrinkToFit(pcell *PaddedCell, bound r2.Rect) CellID {
    961 	shrunkID := pcell.ShrinkToFit(bound)
    962 
    963 	if !s.isFirstUpdate() && shrunkID != pcell.CellID() {
    964 		// Don't shrink any smaller than the existing index cells, since we need
    965 		// to combine the new edges with those cells.
    966 		iter := s.Iterator()
    967 		if iter.LocateCellID(shrunkID) == Indexed {
    968 			shrunkID = iter.CellID()
    969 		}
    970 	}
    971 	return shrunkID
    972 }
    973 
    974 // skipCellRange skips over the cells in the given range, creating index cells if we are
    975 // currently in the interior of at least one shape.
    976 func (s *ShapeIndex) skipCellRange(begin, end CellID, t *tracker, disjointFromIndex bool) {
    977 	// If we aren't in the interior of a shape, then skipping over cells is easy.
    978 	if len(t.shapeIDs) == 0 {
    979 		return
    980 	}
    981 
    982 	// Otherwise generate the list of cell ids that we need to visit, and create
    983 	// an index entry for each one.
    984 	skipped := CellUnionFromRange(begin, end)
    985 	for _, cell := range skipped {
    986 		var clippedEdges []*clippedEdge
    987 		s.updateEdges(PaddedCellFromCellID(cell, cellPadding), clippedEdges, t, disjointFromIndex)
    988 	}
    989 }
    990 
    991 // updateEdges adds or removes the given edges whose bounding boxes intersect a
    992 // given cell. disjointFromIndex is an optimization hint indicating that cellMap
    993 // does not contain any entries that overlap the given cell.
    994 func (s *ShapeIndex) updateEdges(pcell *PaddedCell, edges []*clippedEdge, t *tracker, disjointFromIndex bool) {
    995 	// This function is recursive with a maximum recursion depth of 30 (maxLevel).
    996 
    997 	// Incremental updates are handled as follows. All edges being added or
    998 	// removed are combined together in edges, and all shapes with interiors
    999 	// are tracked using tracker. We subdivide recursively as usual until we
   1000 	// encounter an existing index cell. At this point we absorb the index
   1001 	// cell as follows:
   1002 	//
   1003 	//   - Edges and shapes that are being removed are deleted from edges and
   1004 	//     tracker.
   1005 	//   - All remaining edges and shapes from the index cell are added to
   1006 	//     edges and tracker.
   1007 	//   - Continue subdividing recursively, creating new index cells as needed.
   1008 	//   - When the recursion gets back to the cell that was absorbed, we
   1009 	//     restore edges and tracker to their previous state.
   1010 	//
   1011 	// Note that the only reason that we include removed shapes in the recursive
   1012 	// subdivision process is so that we can find all of the index cells that
   1013 	// contain those shapes efficiently, without maintaining an explicit list of
   1014 	// index cells for each shape (which would be expensive in terms of memory).
   1015 	indexCellAbsorbed := false
   1016 	if !disjointFromIndex {
   1017 		// There may be existing index cells contained inside pcell. If we
   1018 		// encounter such a cell, we need to combine the edges being updated with
   1019 		// the existing cell contents by absorbing the cell.
   1020 		iter := s.Iterator()
   1021 		r := iter.LocateCellID(pcell.id)
   1022 		if r == Disjoint {
   1023 			disjointFromIndex = true
   1024 		} else if r == Indexed {
   1025 			// Absorb the index cell by transferring its contents to edges and
   1026 			// deleting it. We also start tracking the interior of any new shapes.
   1027 			s.absorbIndexCell(pcell, iter, edges, t)
   1028 			indexCellAbsorbed = true
   1029 			disjointFromIndex = true
   1030 		} else {
   1031 			// DCHECK_EQ(SUBDIVIDED, r)
   1032 		}
   1033 	}
   1034 
   1035 	// If there are existing index cells below us, then we need to keep
   1036 	// subdividing so that we can merge with those cells. Otherwise,
   1037 	// makeIndexCell checks if the number of edges is small enough, and creates
   1038 	// an index cell if possible (returning true when it does so).
   1039 	if !disjointFromIndex || !s.makeIndexCell(pcell, edges, t) {
   1040 		// TODO(roberts): If it turns out to have memory problems when there
   1041 		// are 10M+ edges in the index, look into pre-allocating space so we
   1042 		// are not always appending.
   1043 		childEdges := [2][2][]*clippedEdge{} // [i][j]
   1044 
   1045 		// Compute the middle of the padded cell, defined as the rectangle in
   1046 		// (u,v)-space that belongs to all four (padded) children. By comparing
   1047 		// against the four boundaries of middle we can determine which children
   1048 		// each edge needs to be propagated to.
   1049 		middle := pcell.Middle()
   1050 
   1051 		// Build up a vector edges to be passed to each child cell. The (i,j)
   1052 		// directions are left (i=0), right (i=1), lower (j=0), and upper (j=1).
   1053 		// Note that the vast majority of edges are propagated to a single child.
   1054 		for _, edge := range edges {
   1055 			if edge.bound.X.Hi <= middle.X.Lo {
   1056 				// Edge is entirely contained in the two left children.
   1057 				a, b := s.clipVAxis(edge, middle.Y)
   1058 				if a != nil {
   1059 					childEdges[0][0] = append(childEdges[0][0], a)
   1060 				}
   1061 				if b != nil {
   1062 					childEdges[0][1] = append(childEdges[0][1], b)
   1063 				}
   1064 			} else if edge.bound.X.Lo >= middle.X.Hi {
   1065 				// Edge is entirely contained in the two right children.
   1066 				a, b := s.clipVAxis(edge, middle.Y)
   1067 				if a != nil {
   1068 					childEdges[1][0] = append(childEdges[1][0], a)
   1069 				}
   1070 				if b != nil {
   1071 					childEdges[1][1] = append(childEdges[1][1], b)
   1072 				}
   1073 			} else if edge.bound.Y.Hi <= middle.Y.Lo {
   1074 				// Edge is entirely contained in the two lower children.
   1075 				if a := s.clipUBound(edge, 1, middle.X.Hi); a != nil {
   1076 					childEdges[0][0] = append(childEdges[0][0], a)
   1077 				}
   1078 				if b := s.clipUBound(edge, 0, middle.X.Lo); b != nil {
   1079 					childEdges[1][0] = append(childEdges[1][0], b)
   1080 				}
   1081 			} else if edge.bound.Y.Lo >= middle.Y.Hi {
   1082 				// Edge is entirely contained in the two upper children.
   1083 				if a := s.clipUBound(edge, 1, middle.X.Hi); a != nil {
   1084 					childEdges[0][1] = append(childEdges[0][1], a)
   1085 				}
   1086 				if b := s.clipUBound(edge, 0, middle.X.Lo); b != nil {
   1087 					childEdges[1][1] = append(childEdges[1][1], b)
   1088 				}
   1089 			} else {
   1090 				// The edge bound spans all four children. The edge
   1091 				// itself intersects either three or four padded children.
   1092 				left := s.clipUBound(edge, 1, middle.X.Hi)
   1093 				a, b := s.clipVAxis(left, middle.Y)
   1094 				if a != nil {
   1095 					childEdges[0][0] = append(childEdges[0][0], a)
   1096 				}
   1097 				if b != nil {
   1098 					childEdges[0][1] = append(childEdges[0][1], b)
   1099 				}
   1100 				right := s.clipUBound(edge, 0, middle.X.Lo)
   1101 				a, b = s.clipVAxis(right, middle.Y)
   1102 				if a != nil {
   1103 					childEdges[1][0] = append(childEdges[1][0], a)
   1104 				}
   1105 				if b != nil {
   1106 					childEdges[1][1] = append(childEdges[1][1], b)
   1107 				}
   1108 			}
   1109 		}
   1110 
   1111 		// Now recursively update the edges in each child. We call the children in
   1112 		// increasing order of CellID so that when the index is first constructed,
   1113 		// all insertions into cellMap are at the end (which is much faster).
   1114 		for pos := 0; pos < 4; pos++ {
   1115 			i, j := pcell.ChildIJ(pos)
   1116 			if len(childEdges[i][j]) > 0 || len(t.shapeIDs) > 0 {
   1117 				s.updateEdges(PaddedCellFromParentIJ(pcell, i, j), childEdges[i][j],
   1118 					t, disjointFromIndex)
   1119 			}
   1120 		}
   1121 	}
   1122 
   1123 	if indexCellAbsorbed {
   1124 		// Restore the state for any edges being removed that we are tracking.
   1125 		t.restoreStateBefore(s.pendingAdditionsPos)
   1126 	}
   1127 }
   1128 
   1129 // makeIndexCell builds an indexCell from the given padded cell and set of edges and adds
   1130 // it to the index. If the cell or edges are empty, no cell is added.
   1131 func (s *ShapeIndex) makeIndexCell(p *PaddedCell, edges []*clippedEdge, t *tracker) bool {
   1132 	// If the cell is empty, no index cell is needed. (In most cases this
   1133 	// situation is detected before we get to this point, but this can happen
   1134 	// when all shapes in a cell are removed.)
   1135 	if len(edges) == 0 && len(t.shapeIDs) == 0 {
   1136 		return true
   1137 	}
   1138 
   1139 	// Count the number of edges that have not reached their maximum level yet.
   1140 	// Return false if there are too many such edges.
   1141 	count := 0
   1142 	for _, ce := range edges {
   1143 		if p.Level() < ce.faceEdge.maxLevel {
   1144 			count++
   1145 		}
   1146 
   1147 		if count > s.maxEdgesPerCell {
   1148 			return false
   1149 		}
   1150 	}
   1151 
   1152 	// Possible optimization: Continue subdividing as long as exactly one child
   1153 	// of the padded cell intersects the given edges. This can be done by finding
   1154 	// the bounding box of all the edges and calling ShrinkToFit:
   1155 	//
   1156 	// cellID = p.ShrinkToFit(RectBound(edges));
   1157 	//
   1158 	// Currently this is not beneficial; it slows down construction by 4-25%
   1159 	// (mainly computing the union of the bounding rectangles) and also slows
   1160 	// down queries (since more recursive clipping is required to get down to
   1161 	// the level of a spatial index cell). But it may be worth trying again
   1162 	// once containsCenter is computed and all algorithms are modified to
   1163 	// take advantage of it.
   1164 
   1165 	// We update the InteriorTracker as follows. For every Cell in the index
   1166 	// we construct two edges: one edge from entry vertex of the cell to its
   1167 	// center, and one from the cell center to its exit vertex. Here entry
   1168 	// and exit refer the CellID ordering, i.e. the order in which points
   1169 	// are encountered along the 2 space-filling curve. The exit vertex then
   1170 	// becomes the entry vertex for the next cell in the index, unless there are
   1171 	// one or more empty intervening cells, in which case the InteriorTracker
   1172 	// state is unchanged because the intervening cells have no edges.
   1173 
   1174 	// Shift the InteriorTracker focus point to the center of the current cell.
   1175 	if t.isActive && len(edges) != 0 {
   1176 		if !t.atCellID(p.id) {
   1177 			t.moveTo(p.EntryVertex())
   1178 		}
   1179 		t.drawTo(p.Center())
   1180 		s.testAllEdges(edges, t)
   1181 	}
   1182 
   1183 	// Allocate and fill a new index cell. To get the total number of shapes we
   1184 	// need to merge the shapes associated with the intersecting edges together
   1185 	// with the shapes that happen to contain the cell center.
   1186 	cshapeIDs := t.shapeIDs
   1187 	numShapes := s.countShapes(edges, cshapeIDs)
   1188 	cell := NewShapeIndexCell(numShapes)
   1189 
   1190 	// To fill the index cell we merge the two sources of shapes: edge shapes
   1191 	// (those that have at least one edge that intersects this cell), and
   1192 	// containing shapes (those that contain the cell center). We keep track
   1193 	// of the index of the next intersecting edge and the next containing shape
   1194 	// as we go along. Both sets of shape ids are already sorted.
   1195 	eNext := 0
   1196 	cNextIdx := 0
   1197 	for i := 0; i < numShapes; i++ {
   1198 		var clipped *clippedShape
   1199 		// advance to next value base + i
   1200 		eshapeID := int32(s.Len())
   1201 		cshapeID := eshapeID // Sentinels
   1202 
   1203 		if eNext != len(edges) {
   1204 			eshapeID = edges[eNext].faceEdge.shapeID
   1205 		}
   1206 		if cNextIdx < len(cshapeIDs) {
   1207 			cshapeID = cshapeIDs[cNextIdx]
   1208 		}
   1209 		eBegin := eNext
   1210 		if cshapeID < eshapeID {
   1211 			// The entire cell is in the shape interior.
   1212 			clipped = newClippedShape(cshapeID, 0)
   1213 			clipped.containsCenter = true
   1214 			cNextIdx++
   1215 		} else {
   1216 			// Count the number of edges for this shape and allocate space for them.
   1217 			for eNext < len(edges) && edges[eNext].faceEdge.shapeID == eshapeID {
   1218 				eNext++
   1219 			}
   1220 			clipped = newClippedShape(eshapeID, eNext-eBegin)
   1221 			for e := eBegin; e < eNext; e++ {
   1222 				clipped.edges[e-eBegin] = edges[e].faceEdge.edgeID
   1223 			}
   1224 			if cshapeID == eshapeID {
   1225 				clipped.containsCenter = true
   1226 				cNextIdx++
   1227 			}
   1228 		}
   1229 		cell.shapes[i] = clipped
   1230 	}
   1231 
   1232 	// Add this cell to the map.
   1233 	s.cellMap[p.id] = cell
   1234 	s.cells = append(s.cells, p.id)
   1235 
   1236 	// Shift the tracker focus point to the exit vertex of this cell.
   1237 	if t.isActive && len(edges) != 0 {
   1238 		t.drawTo(p.ExitVertex())
   1239 		s.testAllEdges(edges, t)
   1240 		t.setNextCellID(p.id.Next())
   1241 	}
   1242 	return true
   1243 }
   1244 
   1245 // updateBound updates the specified endpoint of the given clipped edge and returns the
   1246 // resulting clipped edge.
   1247 func (s *ShapeIndex) updateBound(edge *clippedEdge, uEnd int, u float64, vEnd int, v float64) *clippedEdge {
   1248 	c := &clippedEdge{faceEdge: edge.faceEdge}
   1249 	if uEnd == 0 {
   1250 		c.bound.X.Lo = u
   1251 		c.bound.X.Hi = edge.bound.X.Hi
   1252 	} else {
   1253 		c.bound.X.Lo = edge.bound.X.Lo
   1254 		c.bound.X.Hi = u
   1255 	}
   1256 
   1257 	if vEnd == 0 {
   1258 		c.bound.Y.Lo = v
   1259 		c.bound.Y.Hi = edge.bound.Y.Hi
   1260 	} else {
   1261 		c.bound.Y.Lo = edge.bound.Y.Lo
   1262 		c.bound.Y.Hi = v
   1263 	}
   1264 
   1265 	return c
   1266 }
   1267 
   1268 // clipUBound clips the given endpoint (lo=0, hi=1) of the u-axis so that
   1269 // it does not extend past the given value of the given edge.
   1270 func (s *ShapeIndex) clipUBound(edge *clippedEdge, uEnd int, u float64) *clippedEdge {
   1271 	// First check whether the edge actually requires any clipping. (Sometimes
   1272 	// this method is called when clipping is not necessary, e.g. when one edge
   1273 	// endpoint is in the overlap area between two padded child cells.)
   1274 	if uEnd == 0 {
   1275 		if edge.bound.X.Lo >= u {
   1276 			return edge
   1277 		}
   1278 	} else {
   1279 		if edge.bound.X.Hi <= u {
   1280 			return edge
   1281 		}
   1282 	}
   1283 	// We interpolate the new v-value from the endpoints of the original edge.
   1284 	// This has two advantages: (1) we don't need to store the clipped endpoints
   1285 	// at all, just their bounding box; and (2) it avoids the accumulation of
   1286 	// roundoff errors due to repeated interpolations. The result needs to be
   1287 	// clamped to ensure that it is in the appropriate range.
   1288 	e := edge.faceEdge
   1289 	v := edge.bound.Y.ClampPoint(interpolateFloat64(u, e.a.X, e.b.X, e.a.Y, e.b.Y))
   1290 
   1291 	// Determine which endpoint of the v-axis bound to update. If the edge
   1292 	// slope is positive we update the same endpoint, otherwise we update the
   1293 	// opposite endpoint.
   1294 	var vEnd int
   1295 	positiveSlope := (e.a.X > e.b.X) == (e.a.Y > e.b.Y)
   1296 	if (uEnd == 1) == positiveSlope {
   1297 		vEnd = 1
   1298 	}
   1299 	return s.updateBound(edge, uEnd, u, vEnd, v)
   1300 }
   1301 
   1302 // clipVBound clips the given endpoint (lo=0, hi=1) of the v-axis so that
   1303 // it does not extend past the given value of the given edge.
   1304 func (s *ShapeIndex) clipVBound(edge *clippedEdge, vEnd int, v float64) *clippedEdge {
   1305 	if vEnd == 0 {
   1306 		if edge.bound.Y.Lo >= v {
   1307 			return edge
   1308 		}
   1309 	} else {
   1310 		if edge.bound.Y.Hi <= v {
   1311 			return edge
   1312 		}
   1313 	}
   1314 
   1315 	// We interpolate the new v-value from the endpoints of the original edge.
   1316 	// This has two advantages: (1) we don't need to store the clipped endpoints
   1317 	// at all, just their bounding box; and (2) it avoids the accumulation of
   1318 	// roundoff errors due to repeated interpolations. The result needs to be
   1319 	// clamped to ensure that it is in the appropriate range.
   1320 	e := edge.faceEdge
   1321 	u := edge.bound.X.ClampPoint(interpolateFloat64(v, e.a.Y, e.b.Y, e.a.X, e.b.X))
   1322 
   1323 	// Determine which endpoint of the v-axis bound to update. If the edge
   1324 	// slope is positive we update the same endpoint, otherwise we update the
   1325 	// opposite endpoint.
   1326 	var uEnd int
   1327 	positiveSlope := (e.a.X > e.b.X) == (e.a.Y > e.b.Y)
   1328 	if (vEnd == 1) == positiveSlope {
   1329 		uEnd = 1
   1330 	}
   1331 	return s.updateBound(edge, uEnd, u, vEnd, v)
   1332 }
   1333 
   1334 // cliupVAxis returns the given edge clipped to within the boundaries of the middle
   1335 // interval along the v-axis, and adds the result to its children.
   1336 func (s *ShapeIndex) clipVAxis(edge *clippedEdge, middle r1.Interval) (a, b *clippedEdge) {
   1337 	if edge.bound.Y.Hi <= middle.Lo {
   1338 		// Edge is entirely contained in the lower child.
   1339 		return edge, nil
   1340 	} else if edge.bound.Y.Lo >= middle.Hi {
   1341 		// Edge is entirely contained in the upper child.
   1342 		return nil, edge
   1343 	}
   1344 	// The edge bound spans both children.
   1345 	return s.clipVBound(edge, 1, middle.Hi), s.clipVBound(edge, 0, middle.Lo)
   1346 }
   1347 
   1348 // absorbIndexCell absorbs an index cell by transferring its contents to edges
   1349 // and/or "tracker", and then delete this cell from the index. If edges includes
   1350 // any edges that are being removed, this method also updates their
   1351 // InteriorTracker state to correspond to the exit vertex of this cell.
   1352 func (s *ShapeIndex) absorbIndexCell(p *PaddedCell, iter *ShapeIndexIterator, edges []*clippedEdge, t *tracker) {
   1353 	// When we absorb a cell, we erase all the edges that are being removed.
   1354 	// However when we are finished with this cell, we want to restore the state
   1355 	// of those edges (since that is how we find all the index cells that need
   1356 	// to be updated).  The edges themselves are restored automatically when
   1357 	// UpdateEdges returns from its recursive call, but the InteriorTracker
   1358 	// state needs to be restored explicitly.
   1359 	//
   1360 	// Here we first update the InteriorTracker state for removed edges to
   1361 	// correspond to the exit vertex of this cell, and then save the
   1362 	// InteriorTracker state.  This state will be restored by UpdateEdges when
   1363 	// it is finished processing the contents of this cell.
   1364 	if t.isActive && len(edges) != 0 && s.isShapeBeingRemoved(edges[0].faceEdge.shapeID) {
   1365 		// We probably need to update the tracker. ("Probably" because
   1366 		// it's possible that all shapes being removed do not have interiors.)
   1367 		if !t.atCellID(p.id) {
   1368 			t.moveTo(p.EntryVertex())
   1369 		}
   1370 		t.drawTo(p.ExitVertex())
   1371 		t.setNextCellID(p.id.Next())
   1372 		for _, edge := range edges {
   1373 			fe := edge.faceEdge
   1374 			if !s.isShapeBeingRemoved(fe.shapeID) {
   1375 				break // All shapes being removed come first.
   1376 			}
   1377 			if fe.hasInterior {
   1378 				t.testEdge(fe.shapeID, fe.edge)
   1379 			}
   1380 		}
   1381 	}
   1382 
   1383 	// Save the state of the edges being removed, so that it can be restored
   1384 	// when we are finished processing this cell and its children.  We don't
   1385 	// need to save the state of the edges being added because they aren't being
   1386 	// removed from "edges" and will therefore be updated normally as we visit
   1387 	// this cell and its children.
   1388 	t.saveAndClearStateBefore(s.pendingAdditionsPos)
   1389 
   1390 	// Create a faceEdge for each edge in this cell that isn't being removed.
   1391 	var faceEdges []*faceEdge
   1392 	trackerMoved := false
   1393 
   1394 	cell := iter.IndexCell()
   1395 	for _, clipped := range cell.shapes {
   1396 		shapeID := clipped.shapeID
   1397 		shape := s.Shape(shapeID)
   1398 		if shape == nil {
   1399 			continue // This shape is being removed.
   1400 		}
   1401 
   1402 		numClipped := clipped.numEdges()
   1403 
   1404 		// If this shape has an interior, start tracking whether we are inside the
   1405 		// shape. updateEdges wants to know whether the entry vertex of this
   1406 		// cell is inside the shape, but we only know whether the center of the
   1407 		// cell is inside the shape, so we need to test all the edges against the
   1408 		// line segment from the cell center to the entry vertex.
   1409 		edge := &faceEdge{
   1410 			shapeID:     shapeID,
   1411 			hasInterior: shape.Dimension() == 2,
   1412 		}
   1413 
   1414 		if edge.hasInterior {
   1415 			t.addShape(shapeID, clipped.containsCenter)
   1416 			// There might not be any edges in this entire cell (i.e., it might be
   1417 			// in the interior of all shapes), so we delay updating the tracker
   1418 			// until we see the first edge.
   1419 			if !trackerMoved && numClipped > 0 {
   1420 				t.moveTo(p.Center())
   1421 				t.drawTo(p.EntryVertex())
   1422 				t.setNextCellID(p.id)
   1423 				trackerMoved = true
   1424 			}
   1425 		}
   1426 		for i := 0; i < numClipped; i++ {
   1427 			edgeID := clipped.edges[i]
   1428 			edge.edgeID = edgeID
   1429 			edge.edge = shape.Edge(edgeID)
   1430 			edge.maxLevel = maxLevelForEdge(edge.edge)
   1431 			if edge.hasInterior {
   1432 				t.testEdge(shapeID, edge.edge)
   1433 			}
   1434 			var ok bool
   1435 			edge.a, edge.b, ok = ClipToPaddedFace(edge.edge.V0, edge.edge.V1, p.id.Face(), cellPadding)
   1436 			if !ok {
   1437 				panic("invariant failure in ShapeIndex")
   1438 			}
   1439 			faceEdges = append(faceEdges, edge)
   1440 		}
   1441 	}
   1442 	// Now create a clippedEdge for each faceEdge, and put them in "new_edges".
   1443 	var newEdges []*clippedEdge
   1444 	for _, faceEdge := range faceEdges {
   1445 		clipped := &clippedEdge{
   1446 			faceEdge: faceEdge,
   1447 			bound:    clippedEdgeBound(faceEdge.a, faceEdge.b, p.bound),
   1448 		}
   1449 		newEdges = append(newEdges, clipped)
   1450 	}
   1451 
   1452 	// Discard any edges from "edges" that are being removed, and append the
   1453 	// remainder to "newEdges"  (This keeps the edges sorted by shape id.)
   1454 	for i, clipped := range edges {
   1455 		if !s.isShapeBeingRemoved(clipped.faceEdge.shapeID) {
   1456 			newEdges = append(newEdges, edges[i:]...)
   1457 			break
   1458 		}
   1459 	}
   1460 
   1461 	// Update the edge list and delete this cell from the index.
   1462 	edges, newEdges = newEdges, edges
   1463 	delete(s.cellMap, p.id)
   1464 	// TODO(roberts): delete from s.Cells
   1465 }
   1466 
   1467 // testAllEdges calls the trackers testEdge on all edges from shapes that have interiors.
   1468 func (s *ShapeIndex) testAllEdges(edges []*clippedEdge, t *tracker) {
   1469 	for _, edge := range edges {
   1470 		if edge.faceEdge.hasInterior {
   1471 			t.testEdge(edge.faceEdge.shapeID, edge.faceEdge.edge)
   1472 		}
   1473 	}
   1474 }
   1475 
   1476 // countShapes reports the number of distinct shapes that are either associated with the
   1477 // given edges, or that are currently stored in the InteriorTracker.
   1478 func (s *ShapeIndex) countShapes(edges []*clippedEdge, shapeIDs []int32) int {
   1479 	count := 0
   1480 	lastShapeID := int32(-1)
   1481 
   1482 	// next clipped shape id in the shapeIDs list.
   1483 	clippedNext := int32(0)
   1484 	// index of the current element in the shapeIDs list.
   1485 	shapeIDidx := 0
   1486 	for _, edge := range edges {
   1487 		if edge.faceEdge.shapeID == lastShapeID {
   1488 			continue
   1489 		}
   1490 
   1491 		count++
   1492 		lastShapeID = edge.faceEdge.shapeID
   1493 
   1494 		// Skip over any containing shapes up to and including this one,
   1495 		// updating count as appropriate.
   1496 		for ; shapeIDidx < len(shapeIDs); shapeIDidx++ {
   1497 			clippedNext = shapeIDs[shapeIDidx]
   1498 			if clippedNext > lastShapeID {
   1499 				break
   1500 			}
   1501 			if clippedNext < lastShapeID {
   1502 				count++
   1503 			}
   1504 		}
   1505 	}
   1506 
   1507 	// Count any remaining containing shapes.
   1508 	count += len(shapeIDs) - shapeIDidx
   1509 	return count
   1510 }
   1511 
   1512 // maxLevelForEdge reports the maximum level for a given edge.
   1513 func maxLevelForEdge(edge Edge) int {
   1514 	// Compute the maximum cell size for which this edge is considered long.
   1515 	// The calculation does not need to be perfectly accurate, so we use Norm
   1516 	// rather than Angle for speed.
   1517 	cellSize := edge.V0.Sub(edge.V1.Vector).Norm() * cellSizeToLongEdgeRatio
   1518 	// Now return the first level encountered during subdivision where the
   1519 	// average cell size is at most cellSize.
   1520 	return AvgEdgeMetric.MinLevel(cellSize)
   1521 }
   1522 
   1523 // removeShapeInternal does the actual work for removing a given shape from the index.
   1524 func (s *ShapeIndex) removeShapeInternal(removed *removedShape, allEdges [][]faceEdge, t *tracker) {
   1525 	// TODO(roberts): finish the implementation of this.
   1526 }