461 lines
11 KiB
Go
461 lines
11 KiB
Go
package quadkey_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/fiskerinc/cloud-services/pkg/utils/quadkey"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestLatLongToQuadkey(t *testing.T) {
|
|
|
|
tests := map[string]struct {
|
|
lat float64
|
|
long float64
|
|
expectedQuadkeyStr string
|
|
expectedQuadkeyInt uint64
|
|
}{
|
|
"lapalma": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
expectedQuadkeyStr: "02301320022100032301331202320110",
|
|
expectedQuadkeyInt: 3204356230721449492,
|
|
},
|
|
|
|
"london": {
|
|
lat: 51.507822,
|
|
long: -0.162069,
|
|
expectedQuadkeyStr: "03131313113000100311131122203023",
|
|
expectedQuadkeyInt: 3996764367461132491,
|
|
},
|
|
|
|
"null": {
|
|
lat: 0.0,
|
|
long: 0.0,
|
|
expectedQuadkeyStr: "30000000000000000000000000000000",
|
|
expectedQuadkeyInt: 0xC000000000000000,
|
|
},
|
|
|
|
"invalid": {
|
|
lat: -2000.0,
|
|
long: -2000.0,
|
|
expectedQuadkeyStr: "22222222222222222222222222222222",
|
|
expectedQuadkeyInt: 0xAAAAAAAAAAAAAAAA,
|
|
},
|
|
}
|
|
|
|
for tname, tt := range tests {
|
|
t.Run(tname, func(t *testing.T) {
|
|
|
|
qkey := quadkey.LatLongToQuadKey(tt.lat, tt.long)
|
|
qkeyStr := quadkey.QuadkeyStr(qkey)
|
|
|
|
assert.Equal(t, tt.expectedQuadkeyInt, qkey)
|
|
assert.Equal(t, tt.expectedQuadkeyStr, qkeyStr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestQuadkeySearchBuckets(t *testing.T) {
|
|
|
|
tests := map[string]struct {
|
|
lat float64
|
|
long float64
|
|
radius float64
|
|
coarseness float64
|
|
|
|
expectedKeys map[uint64]bool
|
|
expectedBuckets map[uint64]quadkey.QuadkeyBucket
|
|
absentKeys map[uint64]bool //set of keys that should not show up
|
|
}{
|
|
|
|
"invalid": {
|
|
lat: -2000.0,
|
|
long: -2000.0,
|
|
radius: 100.0, //100m
|
|
coarseness: 600000.0, // 600km
|
|
expectedKeys: map[uint64]bool{}, //an invalid quad is generated, and fails every intersect check
|
|
},
|
|
|
|
"null": {
|
|
lat: 0.0,
|
|
long: 0.0,
|
|
radius: 100.0, //100m
|
|
coarseness: 600000.0, // 600km
|
|
expectedKeys: map[uint64]bool{
|
|
0x3FF0000000000000: true, //033333
|
|
0xC000000000000000: true, //300000
|
|
0x6AA0000000000000: true, //122222
|
|
0x9550000000000000: true, //211111
|
|
},
|
|
},
|
|
|
|
"london": {
|
|
lat: 51.507822,
|
|
long: -0.162069,
|
|
radius: 8, //8 meters radius
|
|
coarseness: 8,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x37775C0435400000: true, //0313131311300010031110
|
|
0x37775C0435500000: true, //0313131311300010031111
|
|
0x37775C0460000000: true, //0313131311300010120000
|
|
0x37775C0435600000: true, //0313131311300010031112
|
|
0x37775C0435700000: true, //0313131311300010031113
|
|
0x37775C0460200000: true, //0313131311300010120002
|
|
0x37775C0435C00000: true, //0313131311300010031130
|
|
0x37775C0435D00000: true, //0313131311300010031131
|
|
0x37775C0460800000: true, //0313131311300010120020
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B1D00000: true,
|
|
0x2C782903B1DC8000: true,
|
|
0x2C782903B4000000: true,
|
|
0x2C782903B4080000: true,
|
|
0x2C782903B00C0000: true,
|
|
0x2C782903B4800000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
|
|
//lapalma test cases use quadkeys from visually inspecting mapbox maps
|
|
"lapalma": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8, //8 meters radius
|
|
coarseness: 4, //looking for buckets with width of 4 meters
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B1D80000: true,
|
|
0x2C782903B1DC0000: true,
|
|
0x2C782903B4A00000: true,
|
|
0x2C782903B4A80000: true,
|
|
0x2C782903B1EC0000: true,
|
|
0x2C782903B1F00000: true,
|
|
0x2C782903B1F40000: true,
|
|
0x2C782903B3540000: true,
|
|
0x2C782903B6000000: true,
|
|
0x2C782903B1CC0000: true,
|
|
0x2C782903B1E40000: true,
|
|
0x2C782903B1FC0000: true,
|
|
0x2C782903B3440000: true,
|
|
0x2C782903B4880000: true,
|
|
0x2C782903B1F80000: true,
|
|
0x2C782903B3500000: true,
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B1D00000: true,
|
|
0x2C782903B1DC8000: true,
|
|
0x2C782903B4000000: true,
|
|
0x2C782903B4080000: true,
|
|
0x2C782903B00C0000: true,
|
|
0x2C782903B4800000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
|
|
"lapalma_2": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 8,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B1C00000: true,
|
|
0x2C782903B1D00000: true,
|
|
0x2C782903B4800000: true,
|
|
|
|
0x2C782903B1E00000: true,
|
|
0x2C782903B1F00000: true,
|
|
0x2C782903B4A00000: true,
|
|
|
|
0x2C782903B3400000: true,
|
|
0x2C782903B3500000: true,
|
|
0x2C782903B6000000: true,
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B3440000: true,
|
|
0x2C782903B4880000: true,
|
|
0x2C782903B1F80000: true,
|
|
0x2C78290000000000: true,
|
|
0x2C782903B3000000: true,
|
|
},
|
|
},
|
|
|
|
"lapalma_3": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 32,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B1000000: true,
|
|
0x2C782903B4000000: true,
|
|
0x2C782903B3000000: true,
|
|
0x2C782903B6000000: true,
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B3400000: true,
|
|
0x2C782903B3500000: true,
|
|
0x2C782903B0000000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
|
|
"lapalma_4": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 128, //looking for 128m width nodes
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B0000000: true, //corresponds to 023013200221000323, ~127m width node
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C78000000000000: true,
|
|
0x2C782903B4000000: true,
|
|
0x2C782903B3000000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
|
|
"lapalma_5": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 100000, //looking for 100km width nodes
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C78000000000000: true, //corresponds to 02301320, ~130km width node
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B0000000: true,
|
|
0x2C782903B1F00000: true,
|
|
0x2C782903B4A00000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
|
|
expectedBuckets: map[uint64]quadkey.QuadkeyBucket{
|
|
0x2C78000000000000: {
|
|
0x2C78000000000000,
|
|
7,
|
|
0x2C78000000000000,
|
|
0x2C78FFFFFFFFFFFF,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for tname, tt := range tests {
|
|
t.Run(tname, func(t *testing.T) {
|
|
buckets := quadkey.QuadkeySearchBuckets(tt.lat, tt.long, tt.radius, tt.coarseness)
|
|
|
|
assert.Equal(t, len(tt.expectedKeys), len(buckets))
|
|
for key := range buckets {
|
|
assert.Contains(t, tt.expectedKeys, key)
|
|
}
|
|
|
|
for key, bucket := range tt.expectedBuckets {
|
|
assert.Contains(t, buckets, key)
|
|
|
|
actualBucket, ok := buckets[key]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
assert.Equal(t, bucket.Quadkey, actualBucket.Quadkey)
|
|
assert.Equal(t, bucket.Depth, actualBucket.Depth)
|
|
assert.Equal(t, bucket.Start, actualBucket.Start)
|
|
assert.Equal(t, bucket.End, actualBucket.End)
|
|
}
|
|
|
|
for key := range tt.absentKeys {
|
|
assert.NotContains(t, buckets, key)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestQuadkeyGridBuckets(t *testing.T) {
|
|
|
|
tests := map[string]struct {
|
|
lat float64
|
|
long float64
|
|
radius float64
|
|
coarseness float64
|
|
|
|
expectedKeys map[uint64]bool
|
|
absentKeys map[uint64]bool //set of keys that should not show up
|
|
}{
|
|
|
|
"invalid": {
|
|
lat: -2000.0,
|
|
long: -2000.0,
|
|
radius: 100.0, //100m
|
|
coarseness: 600000.0, // 600km
|
|
expectedKeys: map[uint64]bool{
|
|
0x0000000000000000: true, //clamped lat long. 90, -180
|
|
0xAAA0000000000000: true, //clamped lat long -90, -180
|
|
0xFFF0000000000000: true, //clamped lat long, -90, +180
|
|
0x5550000000000000: true, //clamped lat long, +90, +180
|
|
},
|
|
},
|
|
"null": {
|
|
lat: 0.0,
|
|
long: 0.0,
|
|
radius: 100.0, //1km
|
|
coarseness: 600000.0, // 600km
|
|
expectedKeys: map[uint64]bool{
|
|
0x3FF0000000000000: true, //033333
|
|
0xC000000000000000: true, //300000
|
|
0x6AA0000000000000: true, //122222
|
|
0x9550000000000000: true, //211111
|
|
},
|
|
},
|
|
"london": {
|
|
lat: 51.507822,
|
|
long: -0.162069,
|
|
radius: 8, //8 meters radius
|
|
coarseness: 8,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x37775C0435400000: true, //0313131311300010031110
|
|
0x37775C0435500000: true, //0313131311300010031111
|
|
0x37775C0460000000: true, //0313131311300010120000
|
|
0x37775C0435600000: true, //0313131311300010031112
|
|
0x37775C0435700000: true, //0313131311300010031113
|
|
0x37775C0460200000: true, //0313131311300010120002
|
|
0x37775C0435C00000: true, //0313131311300010031130
|
|
0x37775C0435D00000: true, //0313131311300010031131
|
|
0x37775C0460800000: true, //0313131311300010120020
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B1D00000: true,
|
|
0x2C782903B1DC8000: true,
|
|
0x2C782903B4000000: true,
|
|
0x2C782903B4080000: true,
|
|
0x2C782903B00C0000: true,
|
|
0x2C782903B4800000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
//lapalma test cases use quadkeys from visually inspecting mapbox maps
|
|
"lapalma": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 4,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B1D80000: true,
|
|
0x2C782903B1DC0000: true,
|
|
0x2C782903B4A00000: true,
|
|
0x2C782903B4A80000: true,
|
|
0x2C782903B1EC0000: true,
|
|
0x2C782903B1F00000: true,
|
|
0x2C782903B1F40000: true,
|
|
0x2C782903B3540000: true,
|
|
0x2C782903B6000000: true,
|
|
0x2C782903B1CC0000: true,
|
|
0x2C782903B1E40000: true,
|
|
0x2C782903B1FC0000: true,
|
|
0x2C782903B3440000: true,
|
|
0x2C782903B4880000: true,
|
|
0x2C782903B1F80000: true,
|
|
0x2C782903B3500000: true,
|
|
},
|
|
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B3400000: true,
|
|
0x2C782903B1000000: true,
|
|
0x2C782903B0000000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
|
|
"lapalma_2": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 8,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B1C00000: true,
|
|
0x2C782903B1D00000: true,
|
|
0x2C782903B4800000: true,
|
|
|
|
0x2C782903B1E00000: true,
|
|
0x2C782903B1F00000: true,
|
|
0x2C782903B4A00000: true,
|
|
|
|
0x2C782903B3400000: true,
|
|
0x2C782903B3500000: true,
|
|
0x2C782903B6000000: true,
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B1000000: true,
|
|
0x2C782903B0000000: true,
|
|
0x2C78290000000000: true,
|
|
0x2c782903B4000000: true,
|
|
},
|
|
},
|
|
|
|
"lapalma_3": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 32,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B1000000: true,
|
|
0x2c782903B3000000: true,
|
|
0x2c782903B4000000: true,
|
|
0x2c782903B6000000: true,
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B1F00000: true,
|
|
0x2C782903B4A00000: true,
|
|
0x2C782903B0000000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
|
|
"lapalma_4": {
|
|
lat: 33.86219399999999,
|
|
long: -118.029596,
|
|
radius: 8,
|
|
coarseness: 128,
|
|
|
|
expectedKeys: map[uint64]bool{
|
|
0x2C782903B0000000: true,
|
|
},
|
|
absentKeys: map[uint64]bool{
|
|
0x2C782903B1000000: true,
|
|
0x2C782903B1D00000: true,
|
|
0x2C782903B4800000: true,
|
|
0x2C782903B1CC0000: true,
|
|
0x2C782903B1E40000: true,
|
|
0x2C78290000000000: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
for tname, tt := range tests {
|
|
t.Run(tname, func(t *testing.T) {
|
|
fmt.Println(tname)
|
|
|
|
buckets := quadkey.QuadkeyGridBuckets(tt.lat, tt.long, tt.radius, tt.coarseness)
|
|
|
|
assert.Equal(t, len(tt.expectedKeys), len(buckets))
|
|
for key := range buckets {
|
|
assert.Contains(t, tt.expectedKeys, key)
|
|
}
|
|
|
|
for key := range tt.absentKeys {
|
|
assert.NotContains(t, buckets, key)
|
|
}
|
|
})
|
|
}
|
|
}
|