func()

in s2/polygon.go [187:252]


func (p *Polygon) Invert() {
	// Inverting any one loop will invert the polygon.  The best loop to invert
	// is the one whose area is largest, since this yields the smallest area
	// after inversion. The loop with the largest area is always at depth 0.
	// The descendents of this loop all have their depth reduced by 1, while the
	// former siblings of this loop all have their depth increased by 1.

	// The empty and full polygons are handled specially.
	if p.IsEmpty() {
		*p = *FullPolygon()
		p.initLoopProperties()
		return
	}
	if p.IsFull() {
		*p = Polygon{}
		p.initLoopProperties()
		return
	}

	// Find the loop whose area is largest (i.e., whose turning angle is
	// smallest), minimizing calls to TurningAngle(). In particular, for
	// polygons with a single shell at level 0 there is no need to call
	// TurningAngle() at all. (This method is relatively expensive.)
	best := 0
	const none = 10.0 // Flag that means "not computed yet"
	bestAngle := none
	for i := 1; i < p.NumLoops(); i++ {
		if p.Loop(i).depth != 0 {
			continue
		}
		// We defer computing the turning angle of loop 0 until we discover
		// that the polygon has another top-level shell.
		if bestAngle == none {
			bestAngle = p.Loop(best).TurningAngle()
		}
		angle := p.Loop(i).TurningAngle()
		// We break ties deterministically in order to avoid having the output
		// depend on the input order of the loops.
		if angle < bestAngle || (angle == bestAngle && compareLoops(p.Loop(i), p.Loop(best)) < 0) {
			best = i
			bestAngle = angle
		}
	}
	// Build the new loops vector, starting with the inverted loop.
	p.Loop(best).Invert()
	newLoops := make([]*Loop, 0, p.NumLoops())
	// Add the former siblings of this loop as descendants.
	lastBest := p.LastDescendant(best)
	newLoops = append(newLoops, p.Loop(best))
	for i, l := range p.Loops() {
		if i < best || i > lastBest {
			l.depth++
			newLoops = append(newLoops, l)
		}
	}
	// Add the former children of this loop as siblings.
	for i, l := range p.Loops() {
		if i > best && i <= lastBest {
			l.depth--
			newLoops = append(newLoops, l)
		}
	}

	p.loops = newLoops
	p.initLoopProperties()
}