func encodePointCompressed(e *encoder, pi, qi uint32, level int, piCoder, qiCoder *nthDerivativeCoder) {
	zzPi := zigzagEncode(piCoder.encode(int32(pi)))
	zzQi := zigzagEncode(qiCoder.encode(int32(qi)))
	interleaved := interleaveUint32(zzPi, zzQi)
	e.writeUvarint(interleaved)
}
encodePointCompressed encodes points into e.
Given a sequence of Points assumed to be the center of level-k cells,
compresses it into a stream using the following method:
- decompose the points into (face, si, ti) tuples.
- run-length encode the faces, combining face number and count into a
varint32. See the faceRun struct.
- right shift the (si, ti) to remove the part that's constant for all cells
of level-k. The result is called the (pi, qi) space.
- 2nd derivative encode the pi and qi sequences (linear prediction)
- zig-zag encode all derivative values but the first, which cannot be
negative
- interleave the zig-zag encoded values
- encode the first interleaved value in a fixed length encoding
(varint would make this value larger)
- encode the remaining interleaved values as varint64s, as the
derivative encoding should make the values small.
In addition, provides a lossless method to compress a sequence of points even
if some points are not the center of level-k cells. These points are stored
exactly, using 3 double precision values, after the above encoded string,
together with their index in the sequence (this leads to some redundancy - it
is expected that only a small fraction of the points are not cell centers).

To encode leaf cells, this requires 8 bytes for the first vertex plus
an average of 3.8 bytes for each additional vertex, when computed on
Google's geographic repository.
package s2
import (
	"errors"
	"fmt"
	"github.com/golang/geo/r3"
)
const maxEncodedVertices = 50000000
type xyzFaceSiTi struct {
	xyz    Point
	face   int
	si, ti uint32
	level  int
}
const derivativeEncodingOrder = 2
func appendFace(faces []faceRun, face int) []faceRun {
	if len(faces) == 0 || faces[len(faces)-1].face != face {
		return append(faces, faceRun{face, 1})
	}
	faces[len(faces)-1].count++
	return faces
}
func encodePointsCompressed(e *encoder, vertices []xyzFaceSiTi, level int) {
	var faces []faceRun
	for _, v := range vertices {
		faces = appendFace(faces, v.face)
	}
	encodeFaces(e, faces)
	type piQi struct {
		pi, qi uint32
	}
	verticesPiQi := make([]piQi, len(vertices))
	for i, v := range vertices {
		verticesPiQi[i] = piQi{siTitoPiQi(v.si, level), siTitoPiQi(v.ti, level)}
	}
	piCoder, qiCoder := newNthDerivativeCoder(derivativeEncodingOrder), newNthDerivativeCoder(derivativeEncodingOrder)
	for i, v := range verticesPiQi {
		f := encodePointCompressed
		if i == 0 {
			f = encodeFirstPointFixedLength
		}
		f(e, v.pi, v.qi, level, piCoder, qiCoder)
	}
	var offCenter []int
	for i, v := range vertices {
		if v.level != level {
			offCenter = append(offCenter, i)
		}
	}
	e.writeUvarint(uint64(len(offCenter)))
	for _, idx := range offCenter {
		e.writeUvarint(uint64(idx))
		e.writeFloat64(vertices[idx].xyz.X)
		e.writeFloat64(vertices[idx].xyz.Y)
		e.writeFloat64(vertices[idx].xyz.Z)
	}
}
func encodeFirstPointFixedLength(e *encoder, pi, qi uint32, level int, piCoder, qiCoder *nthDerivativeCoder) {
	codedPi, codedQi := piCoder.encode(int32(pi)), qiCoder.encode(int32(qi))
	interleaved := interleaveUint32(uint32(codedPi), uint32(codedQi))
	bytesRequired := (level + 7) / 8 * 2
	for i := 0; i < bytesRequired; i++ {
		e.writeUint8(uint8(interleaved))
		interleaved >>= 8
	}
}