Ejemplo n.º 1
0
// 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]
}
Ejemplo n.º 2
0
// 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)
}