mirror of https://github.com/tidwall/tile38.git
Move iterating up to the cursor before any tests.
This commit is contained in:
parent
f45d81d692
commit
b94f3685b6
|
@ -497,14 +497,21 @@ func (c *Collection) geoSparseInner(
|
||||||
// Within returns all object that are fully contained within an object or
|
// Within returns all object that are fully contained within an object or
|
||||||
// bounding box. Set obj to nil in order to use the bounding box.
|
// bounding box. Set obj to nil in order to use the bounding box.
|
||||||
func (c *Collection) Within(
|
func (c *Collection) Within(
|
||||||
obj geojson.Object, sparse uint8,
|
obj geojson.Object,
|
||||||
|
offset uint64,
|
||||||
|
sparse uint8,
|
||||||
iter func(id string, obj geojson.Object, fields []float64) bool,
|
iter func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
|
var count uint64
|
||||||
if sparse > 0 {
|
if sparse > 0 {
|
||||||
return c.geoSparse(obj, sparse,
|
return c.geoSparse(obj, sparse,
|
||||||
func(id string, o geojson.Object, fields []float64) (
|
func(id string, o geojson.Object, fields []float64) (
|
||||||
match, ok bool,
|
match, ok bool,
|
||||||
) {
|
) {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
if match = o.Within(obj); match {
|
if match = o.Within(obj); match {
|
||||||
ok = iter(id, o, fields)
|
ok = iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -514,6 +521,10 @@ func (c *Collection) Within(
|
||||||
}
|
}
|
||||||
return c.geoSearch(obj.Rect(),
|
return c.geoSearch(obj.Rect(),
|
||||||
func(id string, o geojson.Object, fields []float64) bool {
|
func(id string, o geojson.Object, fields []float64) bool {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if o.Within(obj) {
|
if o.Within(obj) {
|
||||||
return iter(id, o, fields)
|
return iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -525,14 +536,21 @@ func (c *Collection) Within(
|
||||||
// Intersects returns all object that are intersect an object or bounding box.
|
// Intersects returns all object that are intersect an object or bounding box.
|
||||||
// Set obj to nil in order to use the bounding box.
|
// Set obj to nil in order to use the bounding box.
|
||||||
func (c *Collection) Intersects(
|
func (c *Collection) Intersects(
|
||||||
obj geojson.Object, sparse uint8,
|
obj geojson.Object,
|
||||||
|
offset uint64,
|
||||||
|
sparse uint8,
|
||||||
iter func(id string, obj geojson.Object, fields []float64) bool,
|
iter func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
|
var count uint64
|
||||||
if sparse > 0 {
|
if sparse > 0 {
|
||||||
return c.geoSparse(obj, sparse,
|
return c.geoSparse(obj, sparse,
|
||||||
func(id string, o geojson.Object, fields []float64) (
|
func(id string, o geojson.Object, fields []float64) (
|
||||||
match, ok bool,
|
match, ok bool,
|
||||||
) {
|
) {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
if match = o.Intersects(obj); match {
|
if match = o.Intersects(obj); match {
|
||||||
ok = iter(id, o, fields)
|
ok = iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -542,6 +560,10 @@ func (c *Collection) Intersects(
|
||||||
}
|
}
|
||||||
return c.geoSearch(obj.Rect(),
|
return c.geoSearch(obj.Rect(),
|
||||||
func(id string, o geojson.Object, fields []float64) bool {
|
func(id string, o geojson.Object, fields []float64) bool {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if o.Intersects(obj) {
|
if o.Intersects(obj) {
|
||||||
return iter(id, o, fields)
|
return iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -553,14 +575,20 @@ func (c *Collection) Intersects(
|
||||||
// Nearby returns the nearest neighbors
|
// Nearby returns the nearest neighbors
|
||||||
func (c *Collection) Nearby(
|
func (c *Collection) Nearby(
|
||||||
target geojson.Object,
|
target geojson.Object,
|
||||||
|
offset uint64,
|
||||||
iter func(id string, obj geojson.Object, fields []float64) bool,
|
iter func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
alive := true
|
alive := true
|
||||||
center := target.Center()
|
center := target.Center()
|
||||||
|
var count uint64
|
||||||
c.index.Nearby(
|
c.index.Nearby(
|
||||||
[]float64{center.X, center.Y},
|
[]float64{center.X, center.Y},
|
||||||
[]float64{center.X, center.Y},
|
[]float64{center.X, center.Y},
|
||||||
func(_, _ []float64, itemv interface{}) bool {
|
func(_, _ []float64, itemv interface{}) bool {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return true
|
||||||
|
}
|
||||||
item := itemv.(*itemT)
|
item := itemv.(*itemT)
|
||||||
alive = iter(item.id, item.obj, c.getFieldValues(item.id))
|
alive = iter(item.id, item.obj, c.getFieldValues(item.id))
|
||||||
return alive
|
return alive
|
||||||
|
|
|
@ -364,7 +364,7 @@ func fenceMatchRoam(
|
||||||
prevNearbys := fence.roam.nearbys[tid]
|
prevNearbys := fence.roam.nearbys[tid]
|
||||||
var newNearbys map[string]bool
|
var newNearbys map[string]bool
|
||||||
|
|
||||||
col.Intersects(obj, 0, func(
|
col.Intersects(obj, 0, 0, func(
|
||||||
id string, obj2 geojson.Object, fields []float64,
|
id string, obj2 geojson.Object, fields []float64,
|
||||||
) bool {
|
) bool {
|
||||||
if c.hasExpired(fence.roam.key, id) {
|
if c.hasExpired(fence.roam.key, id) {
|
||||||
|
|
|
@ -68,6 +68,7 @@ type ScanWriterParams struct {
|
||||||
noLock bool
|
noLock bool
|
||||||
ignoreGlobMatch bool
|
ignoreGlobMatch bool
|
||||||
clip geojson.Object
|
clip geojson.Object
|
||||||
|
skipTesting bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Server) newScanWriter(
|
func (c *Server) newScanWriter(
|
||||||
|
@ -324,28 +325,38 @@ func (sw *scanWriter) globMatch(id string, o geojson.Object) (ok, keepGoing bool
|
||||||
return true, true
|
return true, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ok is whether the object passes the test and should be written
|
||||||
|
// keepGoing is whether there could be more objects to test
|
||||||
|
func (sw *scanWriter) testObject(id string, o geojson.Object, fields []float64, ignoreGlobMatch bool) (
|
||||||
|
ok, keepGoing bool, fieldVals []float64) {
|
||||||
|
if !ignoreGlobMatch {
|
||||||
|
match, kg := sw.globMatch(id, o)
|
||||||
|
if !match {
|
||||||
|
return true, kg, fieldVals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nf, ok := sw.fieldMatch(fields, o)
|
||||||
|
return ok,true, nf
|
||||||
|
}
|
||||||
|
|
||||||
//id string, o geojson.Object, fields []float64, noLock bool
|
//id string, o geojson.Object, fields []float64, noLock bool
|
||||||
func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
|
func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
|
||||||
if !opts.noLock {
|
if !opts.noLock {
|
||||||
sw.mu.Lock()
|
sw.mu.Lock()
|
||||||
defer sw.mu.Unlock()
|
defer sw.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
var fieldVals []float64
|
||||||
|
var ok bool
|
||||||
keepGoing := true
|
keepGoing := true
|
||||||
if !opts.ignoreGlobMatch {
|
if opts.skipTesting {
|
||||||
var match bool
|
fieldVals = sw.fvals
|
||||||
match, keepGoing = sw.globMatch(opts.id, opts.o)
|
} else {
|
||||||
if !match {
|
ok, keepGoing, fieldVals = sw.testObject(opts.id, opts.o, opts.fields, opts.ignoreGlobMatch)
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nfields, ok := sw.fieldMatch(opts.fields, opts.o)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return keepGoing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sw.count++
|
sw.count++
|
||||||
if sw.count <= sw.cursor {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if sw.output == outputCount {
|
if sw.output == outputCount {
|
||||||
return sw.count < sw.limit
|
return sw.count < sw.limit
|
||||||
}
|
}
|
||||||
|
@ -382,7 +393,7 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
|
||||||
|
|
||||||
} else if len(sw.farr) > 0 {
|
} else if len(sw.farr) > 0 {
|
||||||
jsfields = `,"fields":[`
|
jsfields = `,"fields":[`
|
||||||
for i, field := range nfields {
|
for i, field := range fieldVals {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
jsfields += ","
|
jsfields += ","
|
||||||
}
|
}
|
||||||
|
|
|
@ -383,6 +383,7 @@ func (server *Server) cmdNearby(msg *Message) (res resp.Value, err error) {
|
||||||
distance: distance,
|
distance: distance,
|
||||||
noLock: true,
|
noLock: true,
|
||||||
ignoreGlobMatch: true,
|
ignoreGlobMatch: true,
|
||||||
|
skipTesting: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
server.nearestNeighbors(&s, sw, s.obj.(*geojson.Circle), &matched, iter)
|
server.nearestNeighbors(&s, sw, s.obj.(*geojson.Circle), &matched, iter)
|
||||||
|
@ -406,18 +407,15 @@ func (server *Server) nearestNeighbors(
|
||||||
s *liveFenceSwitches, sw *scanWriter, target *geojson.Circle, matched *uint32,
|
s *liveFenceSwitches, sw *scanWriter, target *geojson.Circle, matched *uint32,
|
||||||
iter func(id string, o geojson.Object, fields []float64, dist *float64,
|
iter func(id string, o geojson.Object, fields []float64, dist *float64,
|
||||||
) bool) {
|
) bool) {
|
||||||
limit := int(sw.cursor + sw.limit)
|
|
||||||
maxDist := target.Haversine()
|
maxDist := target.Haversine()
|
||||||
|
limit := int(sw.limit)
|
||||||
var items []iterItem
|
var items []iterItem
|
||||||
sw.col.Nearby(target, func(id string, o geojson.Object, fields []float64) bool {
|
sw.col.Nearby(target, sw.cursor, func(id string, o geojson.Object, fields []float64) bool {
|
||||||
if server.hasExpired(s.key, id) {
|
if server.hasExpired(s.key, id) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if _, ok := sw.fieldMatch(fields, o); !ok {
|
ok, keepGoing, _ := sw.testObject(id, o, fields,true)
|
||||||
return true
|
if !ok {
|
||||||
}
|
|
||||||
match, keepGoing := sw.globMatch(id, o)
|
|
||||||
if !match {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
dist := target.HaversineTo(o.Center())
|
dist := target.HaversineTo(o.Center())
|
||||||
|
@ -483,7 +481,7 @@ func (server *Server) cmdWithinOrIntersects(cmd string, msg *Message) (res resp.
|
||||||
sw.writeHead()
|
sw.writeHead()
|
||||||
if sw.col != nil {
|
if sw.col != nil {
|
||||||
if cmd == "within" {
|
if cmd == "within" {
|
||||||
sw.col.Within(s.obj, s.sparse, func(
|
sw.col.Within(s.obj, s.cursor, s.sparse, func(
|
||||||
id string, o geojson.Object, fields []float64,
|
id string, o geojson.Object, fields []float64,
|
||||||
) bool {
|
) bool {
|
||||||
if server.hasExpired(s.key, id) {
|
if server.hasExpired(s.key, id) {
|
||||||
|
@ -497,7 +495,7 @@ func (server *Server) cmdWithinOrIntersects(cmd string, msg *Message) (res resp.
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else if cmd == "intersects" {
|
} else if cmd == "intersects" {
|
||||||
sw.col.Intersects(s.obj, s.sparse, func(
|
sw.col.Intersects(s.obj, s.cursor, s.sparse, func(
|
||||||
id string,
|
id string,
|
||||||
o geojson.Object,
|
o geojson.Object,
|
||||||
fields []float64,
|
fields []float64,
|
||||||
|
|
Loading…
Reference in New Issue