2018-10-11 00:25:40 +03:00
|
|
|
package geojson
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"math/rand"
|
|
|
|
"os"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/tidwall/geojson/geometry"
|
|
|
|
"github.com/tidwall/lotsa"
|
|
|
|
)
|
|
|
|
|
|
|
|
func parseCollection(t *testing.T, data string, index bool) Collection {
|
|
|
|
t.Helper()
|
|
|
|
opts := *DefaultParseOptions
|
|
|
|
if index {
|
|
|
|
opts.IndexChildren = 1
|
|
|
|
opts.IndexGeometry = 1
|
|
|
|
} else {
|
|
|
|
opts.IndexChildren = 0
|
|
|
|
opts.IndexGeometry = 0
|
|
|
|
}
|
|
|
|
g, err := Parse(string(data), &opts)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
c, ok := g.(Collection)
|
|
|
|
if !ok {
|
|
|
|
t.Fatal("not searchable")
|
|
|
|
}
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
func testCollectionSubset(
|
|
|
|
t *testing.T, json string, subsetRect geometry.Rect,
|
|
|
|
) []Collection {
|
|
|
|
t.Helper()
|
|
|
|
expectJSON(t, json, nil)
|
|
|
|
start := time.Now()
|
|
|
|
c := parseCollection(t, json, true)
|
|
|
|
dur := time.Since(start)
|
|
|
|
fmt.Printf("%d children in %s\n", len(c.Children()), dur)
|
|
|
|
cs := make([]Collection, 2)
|
|
|
|
ts := make([]time.Duration, 2)
|
|
|
|
start = time.Now()
|
|
|
|
cs[0] = parseCollection(t, json, false)
|
|
|
|
ts[0] = time.Since(start)
|
|
|
|
start = time.Now()
|
|
|
|
cs[1] = parseCollection(t, json, true)
|
|
|
|
ts[1] = time.Since(start)
|
|
|
|
var lastSubset string
|
|
|
|
for i, c := range cs {
|
|
|
|
var children []Object
|
|
|
|
start := time.Now()
|
|
|
|
c.Search(subsetRect, func(child Object) bool {
|
|
|
|
children = append(children, child)
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
dur := time.Since(start)
|
|
|
|
if c.Indexed() {
|
|
|
|
fmt.Printf("Indexed: %v (build: %v)\n", dur, ts[i])
|
|
|
|
} else {
|
|
|
|
fmt.Printf("Simple: %v (build: %v)\n", dur, ts[i])
|
|
|
|
}
|
|
|
|
var childrenJSONs []string
|
|
|
|
for _, child := range children {
|
|
|
|
childrenJSONs = append(childrenJSONs, string(child.AppendJSON(nil)))
|
|
|
|
}
|
|
|
|
sort.Strings(childrenJSONs)
|
|
|
|
subset := `{"type":"GeometryCollection","geometries":[` +
|
|
|
|
strings.Join(childrenJSONs, ",") + `]}`
|
|
|
|
if i > 0 {
|
|
|
|
if subset != lastSubset {
|
|
|
|
t.Fatal("mismatch")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lastSubset = subset
|
|
|
|
}
|
|
|
|
return cs
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionBostonSubset(t *testing.T) {
|
|
|
|
data, err := ioutil.ReadFile("test_files/boston_subset.geojson")
|
|
|
|
expect(t, err == nil)
|
|
|
|
cs := testCollectionSubset(t, string(data),
|
|
|
|
R(-71.474046, 42.492479, -71.466321, 42.497415),
|
|
|
|
)
|
|
|
|
expect(t, cs[0].(Object).Intersects(PO(-71.46723, 42.49432)))
|
|
|
|
expect(t, cs[1].(Object).Intersects(PO(-71.46723, 42.49432)))
|
|
|
|
expect(t, !cs[0].(*FeatureCollection).Intersects(PO(-71.46713, 42.49431)))
|
|
|
|
expect(t, !cs[1].(Object).Intersects(PO(-71.46713, 42.49431)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionUSASubset(t *testing.T) {
|
|
|
|
data, err := ioutil.ReadFile("test_files/usa.geojson")
|
2018-10-16 18:55:26 +03:00
|
|
|
if err != nil {
|
2018-10-11 00:25:40 +03:00
|
|
|
fmt.Printf("test_files/usa.geojson missing\n")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(t, err == nil)
|
|
|
|
cs := testCollectionSubset(t, string(data),
|
|
|
|
R(-90, -45, 90, 45),
|
|
|
|
)
|
|
|
|
expect(t, cs[0].(Object).Intersects(PO(-91.09863, 30.03105)))
|
|
|
|
expect(t, cs[1].(Object).Intersects(PO(-91.09863, 30.03105)))
|
|
|
|
expect(t, !cs[0].(Object).Intersects(PO(-86.87988, 28.439713)))
|
|
|
|
expect(t, !cs[1].(Object).Intersects(PO(-86.87988, 28.439713)))
|
|
|
|
|
|
|
|
N := 10000
|
|
|
|
T := 6
|
|
|
|
|
|
|
|
// 34 is the lower 48
|
|
|
|
rect := cs[0].Children()[34].(Object).Rect()
|
|
|
|
points := make([]Object, N)
|
|
|
|
for i := 0; i < N; i++ {
|
|
|
|
points[i] = PO(
|
|
|
|
(rect.Max.X-rect.Min.X)*rand.Float64()+rect.Min.X,
|
|
|
|
(rect.Max.Y-rect.Min.Y)*rand.Float64()+rect.Min.Y,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
lotsa.Output = os.Stdout
|
|
|
|
cs0 := cs[0].(Object)
|
|
|
|
cs1 := cs[1].(Object)
|
|
|
|
lotsa.Ops(N, T, func(i, _ int) {
|
|
|
|
cs0.Intersects(points[i])
|
|
|
|
})
|
|
|
|
lotsa.Ops(N, T, func(i, _ int) {
|
|
|
|
cs1.Intersects(points[i])
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|