imposm3/cache/binary/deltacoords_test.go

175 lines
3.6 KiB
Go

package binary
import (
"code.google.com/p/goprotobuf/proto"
"github.com/omniscale/imposm3/element"
"math"
"math/rand"
"runtime"
"testing"
)
type fataler interface {
Fatalf(string, ...interface{})
}
func compareNodes(t fataler, a []element.Node, b []element.Node) {
if len(a) != len(b) {
t.Fatalf("length did not match %d != %d", len(a), len(b))
}
for i := range a {
if a[i].Id != b[i].Id {
t.Fatalf("id did not match %d != %d", a[i].Id, b[i].Id)
}
if math.Abs(a[i].Long-b[i].Long) > 1e-7 {
t.Fatalf("long did not match %v != %v", a[i].Long, b[i].Long)
}
if math.Abs(a[i].Lat-b[i].Lat) > 1e-7 {
t.Fatalf("lat did not match %v != %v", a[i].Lat, b[i].Lat)
}
}
}
var nodes []element.Node
func init() {
nodes = make([]element.Node, 64)
offset := rand.Int63n(1e10)
for i := range nodes {
nodes[i] = element.Node{OSMElem: element.OSMElem{Id: offset + rand.Int63n(1000)}, Long: rand.Float64()*360 - 180, Lat: rand.Float64()*180 - 90}
}
}
func TestMarshalDeltaCoords(t *testing.T) {
buf := MarshalDeltaNodes(nodes, nil)
nodes2, _ := UnmarshalDeltaNodes(buf, nil)
compareNodes(t, nodes, nodes2)
}
func BenchmarkMarshalDeltaCoords(b *testing.B) {
var buf []byte
for n := 0; n < b.N; n++ {
buf = MarshalDeltaNodes(nodes, buf)
}
nodes2, _ := UnmarshalDeltaNodes(buf, nil)
compareNodes(b, nodes, nodes2)
runtime.GC()
}
func BenchmarkUnmarshalDeltaCoords(b *testing.B) {
buf := MarshalDeltaNodes(nodes, nil)
var nodes2 []element.Node
for n := 0; n < b.N; n++ {
nodes2, _ = UnmarshalDeltaNodes(buf, nodes2)
}
compareNodes(b, nodes, nodes2)
runtime.GC()
}
func BenchmarkMarshalDeltaCoordsProto(b *testing.B) {
var buf []byte
var err error
for n := 0; n < b.N; n++ {
deltaCoords := packNodes(nodes)
buf, err = proto.Marshal(deltaCoords)
if err != nil {
panic(err)
}
}
deltaCoords := &DeltaCoords{}
err = proto.Unmarshal(buf, deltaCoords)
if err != nil {
panic(err)
}
nodes2 := unpackNodes(deltaCoords, nodes)
compareNodes(b, nodes, nodes2)
runtime.GC()
}
func BenchmarkUnmarshalDeltaCoordsProto(b *testing.B) {
var buf []byte
var err error
deltaCoords := packNodes(nodes)
buf, err = proto.Marshal(deltaCoords)
if err != nil {
panic(err)
}
var nodes2 []element.Node
for n := 0; n < b.N; n++ {
deltaCoords := &DeltaCoords{}
err = proto.Unmarshal(buf, deltaCoords)
if err != nil {
panic(err)
}
nodes2 = unpackNodes(deltaCoords, nodes)
}
compareNodes(b, nodes, nodes2)
runtime.GC()
}
func packNodes(nodes []element.Node) *DeltaCoords {
var lastLon, lastLat int64
var lon, lat int64
var lastId int64
ids := make([]int64, len(nodes))
lons := make([]int64, len(nodes))
lats := make([]int64, len(nodes))
i := 0
for _, nd := range nodes {
lon = int64(CoordToInt(nd.Long))
lat = int64(CoordToInt(nd.Lat))
ids[i] = nd.Id - lastId
lons[i] = lon - lastLon
lats[i] = lat - lastLat
lastId = nd.Id
lastLon = lon
lastLat = lat
i++
}
return &DeltaCoords{Ids: ids, Lats: lats, Lons: lons}
}
func unpackNodes(deltaCoords *DeltaCoords, nodes []element.Node) []element.Node {
if len(deltaCoords.Ids) > cap(nodes) {
nodes = make([]element.Node, len(deltaCoords.Ids))
} else {
nodes = nodes[:len(deltaCoords.Ids)]
}
var lastLon, lastLat int64
var lon, lat int64
var lastId, id int64
for i := 0; i < len(deltaCoords.Ids); i++ {
id = lastId + deltaCoords.Ids[i]
lon = lastLon + deltaCoords.Lons[i]
lat = lastLat + deltaCoords.Lats[i]
nodes[i] = element.Node{
OSMElem: element.OSMElem{Id: int64(id)},
Long: IntToCoord(uint32(lon)),
Lat: IntToCoord(uint32(lat)),
}
lastId = id
lastLon = lon
lastLat = lat
}
return nodes
}