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
|
||||
// bounding box. Set obj to nil in order to use the bounding box.
|
||||
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,
|
||||
) bool {
|
||||
var count uint64
|
||||
if sparse > 0 {
|
||||
return c.geoSparse(obj, sparse,
|
||||
func(id string, o geojson.Object, fields []float64) (
|
||||
match, ok bool,
|
||||
) {
|
||||
count++
|
||||
if count <= offset {
|
||||
return false, true
|
||||
}
|
||||
if match = o.Within(obj); match {
|
||||
ok = iter(id, o, fields)
|
||||
}
|
||||
|
@ -514,6 +521,10 @@ func (c *Collection) Within(
|
|||
}
|
||||
return c.geoSearch(obj.Rect(),
|
||||
func(id string, o geojson.Object, fields []float64) bool {
|
||||
count++
|
||||
if count <= offset {
|
||||
return true
|
||||
}
|
||||
if o.Within(obj) {
|
||||
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.
|
||||
// Set obj to nil in order to use the bounding box.
|
||||
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,
|
||||
) bool {
|
||||
var count uint64
|
||||
if sparse > 0 {
|
||||
return c.geoSparse(obj, sparse,
|
||||
func(id string, o geojson.Object, fields []float64) (
|
||||
match, ok bool,
|
||||
) {
|
||||
count++
|
||||
if count <= offset {
|
||||
return false, true
|
||||
}
|
||||
if match = o.Intersects(obj); match {
|
||||
ok = iter(id, o, fields)
|
||||
}
|
||||
|
@ -542,6 +560,10 @@ func (c *Collection) Intersects(
|
|||
}
|
||||
return c.geoSearch(obj.Rect(),
|
||||
func(id string, o geojson.Object, fields []float64) bool {
|
||||
count++
|
||||
if count <= offset {
|
||||
return true
|
||||
}
|
||||
if o.Intersects(obj) {
|
||||
return iter(id, o, fields)
|
||||
}
|
||||
|
@ -553,14 +575,20 @@ func (c *Collection) Intersects(
|
|||
// Nearby returns the nearest neighbors
|
||||
func (c *Collection) Nearby(
|
||||
target geojson.Object,
|
||||
offset uint64,
|
||||
iter func(id string, obj geojson.Object, fields []float64) bool,
|
||||
) bool {
|
||||
alive := true
|
||||
center := target.Center()
|
||||
var count uint64
|
||||
c.index.Nearby(
|
||||
[]float64{center.X, center.Y},
|
||||
[]float64{center.X, center.Y},
|
||||
func(_, _ []float64, itemv interface{}) bool {
|
||||
count++
|
||||
if count <= offset {
|
||||
return true
|
||||
}
|
||||
item := itemv.(*itemT)
|
||||
alive = iter(item.id, item.obj, c.getFieldValues(item.id))
|
||||
return alive
|
||||
|
|
|
@ -364,7 +364,7 @@ func fenceMatchRoam(
|
|||
prevNearbys := fence.roam.nearbys[tid]
|
||||
var newNearbys map[string]bool
|
||||
|
||||
col.Intersects(obj, 0, func(
|
||||
col.Intersects(obj, 0, 0, func(
|
||||
id string, obj2 geojson.Object, fields []float64,
|
||||
) bool {
|
||||
if c.hasExpired(fence.roam.key, id) {
|
||||
|
|
|
@ -68,6 +68,7 @@ type ScanWriterParams struct {
|
|||
noLock bool
|
||||
ignoreGlobMatch bool
|
||||
clip geojson.Object
|
||||
skipTesting bool
|
||||
}
|
||||
|
||||
func (c *Server) newScanWriter(
|
||||
|
@ -324,28 +325,38 @@ func (sw *scanWriter) globMatch(id string, o geojson.Object) (ok, keepGoing bool
|
|||
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
|
||||
func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
|
||||
if !opts.noLock {
|
||||
sw.mu.Lock()
|
||||
defer sw.mu.Unlock()
|
||||
}
|
||||
var fieldVals []float64
|
||||
var ok bool
|
||||
keepGoing := true
|
||||
if !opts.ignoreGlobMatch {
|
||||
var match bool
|
||||
match, keepGoing = sw.globMatch(opts.id, opts.o)
|
||||
if !match {
|
||||
return true
|
||||
if opts.skipTesting {
|
||||
fieldVals = sw.fvals
|
||||
} else {
|
||||
ok, keepGoing, fieldVals = sw.testObject(opts.id, opts.o, opts.fields, opts.ignoreGlobMatch)
|
||||
if !ok {
|
||||
return keepGoing
|
||||
}
|
||||
}
|
||||
nfields, ok := sw.fieldMatch(opts.fields, opts.o)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
sw.count++
|
||||
if sw.count <= sw.cursor {
|
||||
return true
|
||||
}
|
||||
if sw.output == outputCount {
|
||||
return sw.count < sw.limit
|
||||
}
|
||||
|
@ -382,7 +393,7 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
|
|||
|
||||
} else if len(sw.farr) > 0 {
|
||||
jsfields = `,"fields":[`
|
||||
for i, field := range nfields {
|
||||
for i, field := range fieldVals {
|
||||
if i > 0 {
|
||||
jsfields += ","
|
||||
}
|
||||
|
|
|
@ -383,6 +383,7 @@ func (server *Server) cmdNearby(msg *Message) (res resp.Value, err error) {
|
|||
distance: distance,
|
||||
noLock: true,
|
||||
ignoreGlobMatch: true,
|
||||
skipTesting: true,
|
||||
})
|
||||
}
|
||||
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,
|
||||
iter func(id string, o geojson.Object, fields []float64, dist *float64,
|
||||
) bool) {
|
||||
limit := int(sw.cursor + sw.limit)
|
||||
maxDist := target.Haversine()
|
||||
limit := int(sw.limit)
|
||||
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) {
|
||||
return true
|
||||
}
|
||||
if _, ok := sw.fieldMatch(fields, o); !ok {
|
||||
return true
|
||||
}
|
||||
match, keepGoing := sw.globMatch(id, o)
|
||||
if !match {
|
||||
ok, keepGoing, _ := sw.testObject(id, o, fields,true)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
dist := target.HaversineTo(o.Center())
|
||||
|
@ -483,7 +481,7 @@ func (server *Server) cmdWithinOrIntersects(cmd string, msg *Message) (res resp.
|
|||
sw.writeHead()
|
||||
if sw.col != nil {
|
||||
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,
|
||||
) bool {
|
||||
if server.hasExpired(s.key, id) {
|
||||
|
@ -497,7 +495,7 @@ func (server *Server) cmdWithinOrIntersects(cmd string, msg *Message) (res resp.
|
|||
})
|
||||
})
|
||||
} else if cmd == "intersects" {
|
||||
sw.col.Intersects(s.obj, s.sparse, func(
|
||||
sw.col.Intersects(s.obj, s.cursor, s.sparse, func(
|
||||
id string,
|
||||
o geojson.Object,
|
||||
fields []float64,
|
||||
|
|
Loading…
Reference in New Issue