1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- package utils
- import (
- "bytes"
- )
- const (
- BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz"
- MAX_LATITUDE float64 = 90
- MIN_LATITUDE float64 = -90
- MAX_LONGITUDE float64 = 180
- MIN_LONGITUDE float64 = -180
- )
- var (
- bits = []int{16, 8, 4, 2, 1}
- base32 = []byte(BASE32)
- )
- // Box geohash的精度与其长度成正比
- // 每个点的geohash值实际上代表了一个区域,这个区域的大小与geohash的精度成反比
- // 坐标点的格式为(纬度,经度)
- // 将这个区域用一个矩形表示
- type Box struct {
- MinLat, MaxLat float64 // 纬度
- MinLng, MaxLng float64 // 经度
- }
- func (this *Box) Width() float64 {
- return this.MaxLng - this.MinLng
- }
- func (this *Box) Height() float64 {
- return this.MaxLat - this.MinLat
- }
- // GeoHashEncode 输入值:纬度,经度,精度(geohash的长度)
- // 返回geohash, 以及该点所在的区域
- func GeoHashEncode(latitude, longitude float64, precision int) (string, *Box) {
- var geohash bytes.Buffer
- var minLat, maxLat float64 = MIN_LATITUDE, MAX_LATITUDE
- var minLng, maxLng float64 = MIN_LONGITUDE, MAX_LONGITUDE
- var mid float64 = 0
- bit, ch, length, isEven := 0, 0, 0, true
- for length < precision {
- if isEven {
- if mid = (minLng + maxLng) / 2; mid < longitude {
- ch |= bits[bit]
- minLng = mid
- } else {
- maxLng = mid
- }
- } else {
- if mid = (minLat + maxLat) / 2; mid < latitude {
- ch |= bits[bit]
- minLat = mid
- } else {
- maxLat = mid
- }
- }
- isEven = !isEven
- if bit < 4 {
- bit++
- } else {
- geohash.WriteByte(base32[ch])
- length, bit, ch = length+1, 0, 0
- }
- }
- b := &Box{
- MinLat: minLat,
- MaxLat: maxLat,
- MinLng: minLng,
- MaxLng: maxLng,
- }
- return geohash.String(), b
- }
|