tile38: Missing points in 'Nearby' queries
This is another bug I’ve discovered which likely affects tile38 itself, but exists in its collection package:
Certain query conditions cause the index to not return points which are within the given radius. I found these examples basically at random by experiencing them while querying an actual dataset within a project.
Could this have something to do with the wrap-around of longitude from around -180 to around 180? That is what I can immediately gather because queries that are working as expected with large radii seem to return points that are positioned away from longitudes -180/180, while the opposite appears to be true for queries with smaller radii, as shown below:
package main
import (
"fmt"
"encoding/json"
"strconv"
"time"
"math/rand"
"github.com/tidwall/tile38/controller/collection"
"github.com/tidwall/tile38/geojson"
)
const Km = 1000
func main() {
randSrc := rand.NewSource(time.Now().UnixNano())
geoindex := collection.New()
// Insert points ~14.731km apart.
for lng := float64(-180); lng < 180; lng += 0.25 {
for lat := float64(-90); lat < 90; lat += 0.25 {
objBytes, _ := json.Marshal(map[string]interface{}{
"type": "Feature",
"geometry": map[string]interface{}{
"type": "Point",
"coordinates": []interface{}{lng,lat},
},
"properties": map[string]interface{}{
"randomNumber": rand.New(randSrc).Float64(),
},
})
obj, _ := geojson.ObjectAuto(objBytes)
id := strconv.FormatFloat(lng, 'f', -1, 64) + strconv.FormatFloat(lat, 'f', -1, 64)
geoindex.ReplaceOrInsert(id, obj, nil, nil)
}
}
// Append expected objects to here, panic if none are added.
expectedObjects := make([]geojson.Object, 0)
for i := 0; i < 3; i++ {
// Works as expected
geoindex.Nearby(0, 0, -86, 20.25, 18293*Km,
func(_ string, obj geojson.Object, _ []float64) bool {
fmt.Printf("0 [Working] Nearby %v: %v\n", i, obj)
return true
},
)
geoindex.Nearby(0, 0, 84.75, -176, 32*Km,
func(_ string, obj geojson.Object, _ []float64) bool {
fmt.Printf("1 [Working] Nearby %v: %v\n", i, obj)
return true
},
)
// It was expected that the Objects returned below this comment would include
// the Objects returned above it, as the radii are larger and contain them.
// Farthest distance on earth is ~20057.184km or 6384.4km (Earth's max radius,
// at the summit of Chimborazo in Ecuador) * Pi (3.1415927).
geoindex.Nearby(0, 0, -86, 20.25, 20000*Km,
func(_ string, obj geojson.Object, _ []float64) bool {
fmt.Printf("2 [Not Working] Nearby %v: %v\n", i, obj)
expectedObjects = append(expectedObjects, obj)
return true
},
)
geoindex.Nearby(0, 0, 84.75, -176, 64*Km,
func(_ string, obj geojson.Object, _ []float64) bool {
fmt.Printf("3 [Not Working] Nearby %v: %v\n", i, obj)
expectedObjects = append(expectedObjects, obj)
return true
},
)
geoindex.Nearby(0, 0, 84.75, -176, 80*Km,
func(_ string, obj geojson.Object, _ []float64) bool {
fmt.Printf("4 [Not Working] Nearby %v: %v\n", i, obj)
expectedObjects = append(expectedObjects, obj)
return true
},
)
}
if len(expectedObjects) == 0 {
panic("Expected points were missing.")
}
}
I’ll be able to take another look at this sometime within the next two weeks. I’ll let you know if I find out anything new on this.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 15 (14 by maintainers)
Yes, this problem has been fixed.
A radius as large as 900000000 meters or 9000000km might work, though it doesn’t make practical sense because the maximum radius on earth is always less than 20060km, and using the average radius at the equator, is usually around 20016km.
Looks good. Thanks a ton!