imposm3/cache/binary/deltacoords.go

107 lines
2.2 KiB
Go

package binary
import (
"bytes"
"encoding/binary"
"imposm3/element"
)
func MarshalDeltaNodes(nodes []element.Node, buf []byte) []byte {
estimatedLength := len(nodes)*4*3 + binary.MaxVarintLen64
if cap(buf) < estimatedLength {
buf = make([]byte, estimatedLength)
} else {
// resize slice to full capacity
buf = buf[:cap(buf)-1]
}
lastId := int64(0)
nextPos := binary.PutVarint(buf, int64(len(nodes)))
for i := range nodes {
if len(buf)-nextPos < binary.MaxVarintLen64 {
tmp := make([]byte, len(buf)*3/2)
copy(tmp, buf)
buf = tmp
}
nextPos += binary.PutVarint(buf[nextPos:], nodes[i].Id-lastId)
lastId = nodes[i].Id
}
lastLong := int64(0)
for i := range nodes {
if len(buf)-nextPos < binary.MaxVarintLen64 {
tmp := make([]byte, len(buf)*3/2)
copy(tmp, buf)
buf = tmp
}
long := int64(CoordToInt(nodes[i].Long))
nextPos += binary.PutVarint(buf[nextPos:], long-lastLong)
lastLong = long
}
lastLat := int64(0)
for i := range nodes {
if len(buf)-nextPos < binary.MaxVarintLen64 {
tmp := make([]byte, len(buf)*3/2)
copy(tmp, buf)
buf = tmp
}
lat := int64(CoordToInt(nodes[i].Lat))
nextPos += binary.PutVarint(buf[nextPos:], lat-lastLat)
lastLat = lat
}
return buf[:nextPos]
}
func UnmarshalDeltaNodes(buf []byte, nodes []element.Node) ([]element.Node, error) {
r := bytes.NewBuffer(buf)
length, err := binary.ReadVarint(r)
if err != nil {
return nil, err
}
if int64(cap(nodes)) < length {
nodes = make([]element.Node, length)
} else {
nodes = nodes[:length]
}
lastId := int64(0)
for i := 0; int64(i) < length; i++ {
id, err := binary.ReadVarint(r)
if err != nil {
return nil, err
}
id = lastId + id
nodes[i].Id = id
lastId = id
}
lastLong := int64(0)
for i := 0; int64(i) < length; i++ {
long, err := binary.ReadVarint(r)
if err != nil {
return nil, err
}
long = lastLong + long
nodes[i].Long = IntToCoord(uint32(long))
lastLong = long
}
lastLat := int64(0)
for i := 0; int64(i) < length; i++ {
lat, err := binary.ReadVarint(r)
if err != nil {
return nil, err
}
lat = lastLat + lat
nodes[i].Lat = IntToCoord(uint32(lat))
lastLat = lat
}
return nodes, nil
}