func()

in s2/shapeindex.go [1352:1465]


func (s *ShapeIndex) absorbIndexCell(p *PaddedCell, iter *ShapeIndexIterator, edges []*clippedEdge, t *tracker) {
	// When we absorb a cell, we erase all the edges that are being removed.
	// However when we are finished with this cell, we want to restore the state
	// of those edges (since that is how we find all the index cells that need
	// to be updated).  The edges themselves are restored automatically when
	// UpdateEdges returns from its recursive call, but the InteriorTracker
	// state needs to be restored explicitly.
	//
	// Here we first update the InteriorTracker state for removed edges to
	// correspond to the exit vertex of this cell, and then save the
	// InteriorTracker state.  This state will be restored by UpdateEdges when
	// it is finished processing the contents of this cell.
	if t.isActive && len(edges) != 0 && s.isShapeBeingRemoved(edges[0].faceEdge.shapeID) {
		// We probably need to update the tracker. ("Probably" because
		// it's possible that all shapes being removed do not have interiors.)
		if !t.atCellID(p.id) {
			t.moveTo(p.EntryVertex())
		}
		t.drawTo(p.ExitVertex())
		t.setNextCellID(p.id.Next())
		for _, edge := range edges {
			fe := edge.faceEdge
			if !s.isShapeBeingRemoved(fe.shapeID) {
				break // All shapes being removed come first.
			}
			if fe.hasInterior {
				t.testEdge(fe.shapeID, fe.edge)
			}
		}
	}

	// Save the state of the edges being removed, so that it can be restored
	// when we are finished processing this cell and its children.  We don't
	// need to save the state of the edges being added because they aren't being
	// removed from "edges" and will therefore be updated normally as we visit
	// this cell and its children.
	t.saveAndClearStateBefore(s.pendingAdditionsPos)

	// Create a faceEdge for each edge in this cell that isn't being removed.
	var faceEdges []*faceEdge
	trackerMoved := false

	cell := iter.IndexCell()
	for _, clipped := range cell.shapes {
		shapeID := clipped.shapeID
		shape := s.Shape(shapeID)
		if shape == nil {
			continue // This shape is being removed.
		}

		numClipped := clipped.numEdges()

		// If this shape has an interior, start tracking whether we are inside the
		// shape. updateEdges wants to know whether the entry vertex of this
		// cell is inside the shape, but we only know whether the center of the
		// cell is inside the shape, so we need to test all the edges against the
		// line segment from the cell center to the entry vertex.
		edge := &faceEdge{
			shapeID:     shapeID,
			hasInterior: shape.Dimension() == 2,
		}

		if edge.hasInterior {
			t.addShape(shapeID, clipped.containsCenter)
			// There might not be any edges in this entire cell (i.e., it might be
			// in the interior of all shapes), so we delay updating the tracker
			// until we see the first edge.
			if !trackerMoved && numClipped > 0 {
				t.moveTo(p.Center())
				t.drawTo(p.EntryVertex())
				t.setNextCellID(p.id)
				trackerMoved = true
			}
		}
		for i := 0; i < numClipped; i++ {
			edgeID := clipped.edges[i]
			edge.edgeID = edgeID
			edge.edge = shape.Edge(edgeID)
			edge.maxLevel = maxLevelForEdge(edge.edge)
			if edge.hasInterior {
				t.testEdge(shapeID, edge.edge)
			}
			var ok bool
			edge.a, edge.b, ok = ClipToPaddedFace(edge.edge.V0, edge.edge.V1, p.id.Face(), cellPadding)
			if !ok {
				panic("invariant failure in ShapeIndex")
			}
			faceEdges = append(faceEdges, edge)
		}
	}
	// Now create a clippedEdge for each faceEdge, and put them in "new_edges".
	var newEdges []*clippedEdge
	for _, faceEdge := range faceEdges {
		clipped := &clippedEdge{
			faceEdge: faceEdge,
			bound:    clippedEdgeBound(faceEdge.a, faceEdge.b, p.bound),
		}
		newEdges = append(newEdges, clipped)
	}

	// Discard any edges from "edges" that are being removed, and append the
	// remainder to "newEdges"  (This keeps the edges sorted by shape id.)
	for i, clipped := range edges {
		if !s.isShapeBeingRemoved(clipped.faceEdge.shapeID) {
			newEdges = append(newEdges, edges[i:]...)
			break
		}
	}

	// Update the edge list and delete this cell from the index.
	edges, newEdges = newEdges, edges
	delete(s.cellMap, p.id)
	// TODO(roberts): delete from s.Cells
}