Add initial ‘geof’ package for geospatial functions
This commit is contained in:
parent
096984ad05
commit
af00a45721
4 changed files with 183 additions and 0 deletions
111
util/geof/geohash.go
Normal file
111
util/geof/geohash.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package geof
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
var bits = []int{16, 8, 4, 2, 1}
|
||||
|
||||
var latmax = []float64{-90, 90}
|
||||
|
||||
var lngmax = []float64{-180, 180}
|
||||
|
||||
var base32 = []byte("0123456789bcdefghjkmnpqrstuvwxyz")
|
||||
|
||||
func refine(interval []float64, cd, mask int) []float64 {
|
||||
if cd&mask > 0 {
|
||||
interval[0] = (interval[0] + interval[1]) / 2
|
||||
} else {
|
||||
interval[1] = (interval[0] + interval[1]) / 2
|
||||
}
|
||||
return interval
|
||||
}
|
||||
|
||||
func GeohashDecode(hash string) *sql.Point {
|
||||
|
||||
isEven := true
|
||||
lat := latmax
|
||||
lng := lngmax
|
||||
latErr := float64(90)
|
||||
lngErr := float64(180)
|
||||
var c string
|
||||
var cd int
|
||||
|
||||
for i := 0; i < len(hash); i++ {
|
||||
c = hash[i : i+1]
|
||||
cd = bytes.Index(base32, []byte(c))
|
||||
for j := 0; j < 5; j++ {
|
||||
if isEven {
|
||||
lngErr /= 2
|
||||
lng = refine(lng, cd, bits[j])
|
||||
} else {
|
||||
latErr /= 2
|
||||
lat = refine(lat, cd, bits[j])
|
||||
}
|
||||
isEven = !isEven
|
||||
}
|
||||
}
|
||||
|
||||
return sql.NewPoint(
|
||||
(lat[0]+lat[1])/2,
|
||||
(lng[0]+lng[1])/2,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func GeohashEncode(point *sql.Point, precision int64) string {
|
||||
|
||||
isEven := true
|
||||
lat := []float64{-90, 90}
|
||||
lng := []float64{-180, 180}
|
||||
bit := 0
|
||||
ch := 0
|
||||
var geohash bytes.Buffer
|
||||
var mid float64
|
||||
for geohash.Len() < int(precision) {
|
||||
if isEven {
|
||||
mid = (lng[0] + lng[1]) / 2
|
||||
if point.LO > mid {
|
||||
ch |= bits[bit]
|
||||
lng[0] = mid
|
||||
} else {
|
||||
lng[1] = mid
|
||||
}
|
||||
} else {
|
||||
mid = (lat[0] + lat[1]) / 2
|
||||
if point.LA > mid {
|
||||
ch |= bits[bit]
|
||||
lat[0] = mid
|
||||
} else {
|
||||
lat[1] = mid
|
||||
}
|
||||
}
|
||||
isEven = !isEven
|
||||
if bit < 4 {
|
||||
bit++
|
||||
} else {
|
||||
geohash.WriteByte(base32[ch])
|
||||
bit = 0
|
||||
ch = 0
|
||||
}
|
||||
}
|
||||
|
||||
return geohash.String()
|
||||
|
||||
}
|
34
util/geof/haversine.go
Normal file
34
util/geof/haversine.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package geof
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
const earthr float64 = 6371000
|
||||
|
||||
const radian float64 = math.Pi / 180
|
||||
|
||||
func Haversine(a, b *sql.Point) float64 {
|
||||
lata, lnga := a.LA*radian, a.LO*radian
|
||||
latb, lngb := b.LA*radian, b.LO*radian
|
||||
latc, lngc := lata-latb, lnga-lngb
|
||||
dis := math.Pow(math.Sin(latc/2), 2) + math.Cos(lata)*math.Cos(latb)*math.Pow(math.Sin(lngc/2), 2)
|
||||
c := 2 * math.Atan2(math.Sqrt(dis), math.Sqrt(1-dis))
|
||||
return earthr * c
|
||||
}
|
19
util/geof/inside.go
Normal file
19
util/geof/inside.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package geof
|
||||
|
||||
func Inside(a, b interface{}) bool {
|
||||
return false
|
||||
}
|
19
util/geof/intersects.go
Normal file
19
util/geof/intersects.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package geof
|
||||
|
||||
func Intersects(a, b interface{}) bool {
|
||||
return false
|
||||
}
|
Loading…
Reference in a new issue