// SearchLocations around latitude/longitude in bounded area (km) for known location points. func SearchLocations(latitude, longitude, bound float64) []*GeoData { if !searchReady { InitSearch() } hashSteps := geohashEstimateStepsByRadius(bound * 1000) debugf("Hash step: %v, for radius: %v km", hashSteps, bound) var hash C.GeoHashBits C.geohashEncodeWGS84(C.double(latitude), C.double(longitude), C.uint8_t(hashSteps), &hash) neighbours := getNeighbours(uint64(hash.bits), uint8(hashSteps)) box := boundingBox(latitude, longitude, bound) initialSize := 128 // Initial array size to avoid time waste re-sizing array var locationsFound = make([]*GeoData, initialSize) locFoundCount := 0 geoStoreKeysLen := len(geoHashStore) for nIdx := range neighbours { neighboursUpperLimit := (neighbours[nIdx] + 1) << uint((maxSteps-hashSteps)*2) neighbours[nIdx] = neighbours[nIdx] << uint((maxSteps-hashSteps)*2) // debugf("Normalized Neighbours Hash: %v to %v", neighbours[nIdx], neighboursUpperLimit) searchIdx := sort.Search(geoStoreKeysLen, func(i int) bool { return geoHashStore[i].GeoHash >= neighbours[nIdx] }) if searchIdx < geoStoreKeysLen { // Not found would turn index=N // debugf("found location?") // found location for i := searchIdx; i < geoStoreKeysLen; i++ { data := geoHashStore[i] if data.GeoHash < neighboursUpperLimit { //var data *GeoData // debugf("filtering by lat/long: %v %v", data.Latitude, data.Longitude) // debugf("filtering by bounding box: %v %v %v %v", box[0], box[1], box[2], box[3]) // filter by strict bounding box box0 := box[0] box1 := box[1] box2 := box[2] box3 := box[3] lat := data.Latitude lng := data.Longitude if ((lat >= box0 && lat <= box1) || (lat <= box0 && lat >= box1)) && ((lng >= box2 && lng <= box3) || (lng <= box2 && lng >= box3)) { if locFoundCount < initialSize { locationsFound[locFoundCount] = data } else { locationsFound = append(locationsFound, data) } locFoundCount++ // debugf("Search found location in geoHashStore: %v", geoHashStore[searchIdx]) } } else { break } } } } return locationsFound[:locFoundCount] }
// Encode a geo hash to MAX(26) steps func geohashEncodeMax(latitude, longitude float64) uint64 { var hash C.GeoHashBits C.geohashEncodeWGS84(C.double(latitude), C.double(longitude), C.uint8_t(maxSteps), &hash) return uint64(hash.bits) }