mirror of https://github.com/tidwall/tile38.git
knn overscan ordering (#195)
This commit is contained in:
parent
14cc6cedf7
commit
90f87bc3fb
|
@ -279,9 +279,8 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if sw.output == outputCount {
|
if sw.output == outputCount {
|
||||||
return true
|
return sw.count < sw.limit
|
||||||
}
|
}
|
||||||
|
|
||||||
switch sw.msg.OutputType {
|
switch sw.msg.OutputType {
|
||||||
case server.JSON:
|
case server.JSON:
|
||||||
var wr bytes.Buffer
|
var wr bytes.Buffer
|
||||||
|
|
|
@ -2,6 +2,7 @@ package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -304,14 +305,18 @@ func (c *Controller) cmdNearby(msg *server.Message) (res string, err error) {
|
||||||
}
|
}
|
||||||
sw.writeHead()
|
sw.writeHead()
|
||||||
if sw.col != nil {
|
if sw.col != nil {
|
||||||
iter := func(id string, o geojson.Object, fields []float64) bool {
|
iter := func(id string, o geojson.Object, fields []float64, dist *float64) bool {
|
||||||
if c.hasExpired(s.key, id) {
|
if c.hasExpired(s.key, id) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Calculate distance if we need to
|
// Calculate distance if we need to
|
||||||
distance := 0.0
|
distance := 0.0
|
||||||
if s.distance {
|
if s.distance {
|
||||||
distance = o.CalculatedPoint().DistanceTo(geojson.Position{X: s.lon, Y: s.lat, Z: 0})
|
if dist != nil {
|
||||||
|
distance = *dist
|
||||||
|
} else {
|
||||||
|
distance = o.CalculatedPoint().DistanceTo(geojson.Position{X: s.lon, Y: s.lat, Z: 0})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return sw.writeObject(ScanWriterParams{
|
return sw.writeObject(ScanWriterParams{
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -321,9 +326,13 @@ func (c *Controller) cmdNearby(msg *server.Message) (res string, err error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if s.knn {
|
if s.knn {
|
||||||
sw.col.NearestNeighbors(s.lat, s.lon, iter)
|
nearestNeighbors(sw, s.lat, s.lon, iter)
|
||||||
} else {
|
} else {
|
||||||
sw.col.Nearby(s.sparse, s.lat, s.lon, s.meters, minZ, maxZ, iter)
|
sw.col.Nearby(s.sparse, s.lat, s.lon, s.meters, minZ, maxZ,
|
||||||
|
func(id string, o geojson.Object, fields []float64) bool {
|
||||||
|
return iter(id, o, fields, nil)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sw.writeFoot()
|
sw.writeFoot()
|
||||||
|
@ -333,6 +342,39 @@ func (c *Controller) cmdNearby(msg *server.Message) (res string, err error) {
|
||||||
return string(wr.Bytes()), nil
|
return string(wr.Bytes()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type iterItem struct {
|
||||||
|
id string
|
||||||
|
o geojson.Object
|
||||||
|
fields []float64
|
||||||
|
dist float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func nearestNeighbors(sw *scanWriter, lat, lon float64, iter func(id string, o geojson.Object, fields []float64, dist *float64) bool) {
|
||||||
|
limit := sw.limit * 10
|
||||||
|
if limit > limitItems*10 {
|
||||||
|
limit = limitItems * 10
|
||||||
|
}
|
||||||
|
k := sw.cursor + limit
|
||||||
|
var items []iterItem
|
||||||
|
sw.col.NearestNeighbors(lat, lon, func(id string, o geojson.Object, fields []float64) bool {
|
||||||
|
if k == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
dist := o.CalculatedPoint().DistanceTo(geojson.Position{X: lon, Y: lat, Z: 0})
|
||||||
|
items = append(items, iterItem{id: id, o: o, fields: fields, dist: dist})
|
||||||
|
k--
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
sort.Slice(items, func(i, j int) bool {
|
||||||
|
return items[i].dist < items[j].dist
|
||||||
|
})
|
||||||
|
for _, item := range items {
|
||||||
|
if !iter(item.id, item.o, item.fields, &item.dist) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) cmdWithin(msg *server.Message) (res string, err error) {
|
func (c *Controller) cmdWithin(msg *server.Message) (res string, err error) {
|
||||||
return c.cmdWithinOrIntersects("within", msg)
|
return c.cmdWithinOrIntersects("within", msg)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue