-
Notifications
You must be signed in to change notification settings - Fork 0
/
geopoint.go
122 lines (107 loc) · 2.75 KB
/
geopoint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package geopoint
import (
"bytes"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"fmt"
)
//GeoPoint 4326
type GeoPoint struct {
Lng float64 `json:"lng"`
Lat float64 `json:"lat"`
}
//String ...
// point := GeoPoint{Lng: 113.538639, Lat: 34.826563}
// point.String()
// -->postGIS
func (p *GeoPoint) String() string {
return fmt.Sprintf("SRID=4326;POINT(%v %v)", p.Lng, p.Lat)
}
//ToString same function as String()
func (p *GeoPoint) ToString() string {
return p.String()
}
//Value ...
func (p GeoPoint) Value() (driver.Value, error) {
return p.String(), nil
}
//JSONString ...
// 从数据库查询了一条或者多条有GEO点信息的数据ps,那么,可以在循环中使用
// Get one or more GEO points for iteration.
/*
p3 := GeoPoint{Lng: 113.739873, Lat: 34.356696}
ps := PointsInDistanceRange(p3, 5000)
psLen := len(ps)
if psLen > 0 {
for i := 0; i < psLen; i++ {
var p GeoPoint
p.Scan(ps[i].Geog)
ps[i].Geog = p.JSONString()
m, err := json.Marshal(ps[i])
if err != nil {
fmt.Println("error!!")
continue
}
fmt.Println(string(m))
}
}
*/
func (p *GeoPoint) JSONString() string {
return fmt.Sprintf("{lng:%v,lat: %v}", p.Lng, p.Lat)
}
//Scan ...interface {} is *string, not []uint8
// val interface{}
// val string
// ---
// var p2 GeoPoint
// user := GetOneRowFromDB(2)
// p2.Scan(user.Geog)
// fmt.Println(p2.String())
//113.739873, 34.356696
func (p *GeoPoint) Scan(val string) error {
//b, err := hex.DecodeString(string(val.([]uint8)))
b, err := hex.DecodeString(string([]uint8(val)))
if err != nil {
return err
}
r := bytes.NewReader(b)
var wkbByteOrder uint8
if err := binary.Read(r, binary.LittleEndian, &wkbByteOrder); err != nil {
return err
}
var byteOrder binary.ByteOrder
switch wkbByteOrder {
case 0:
byteOrder = binary.BigEndian
case 1:
byteOrder = binary.LittleEndian
default:
return fmt.Errorf("Invalid byte order %d", wkbByteOrder)
}
var wkbGeometryType uint64
if err := binary.Read(r, byteOrder, &wkbGeometryType); err != nil {
return err
}
if err := binary.Read(r, byteOrder, p); err != nil {
return err
}
return nil
}
//GetPointsQueryStringWithIn ...
/*
//PointsInDistanceRange Get points in given distance range to GeoPoint.
func PointsInDistanceRange(p GeoPoint, d int64) []Users {
list := make([]Users, 0)
qStr := p.QueryStringWithIn(d)
engine := getDBEngine()
err := engine.Where(qStr).Desc("id").Find(&list)
if err != nil {
log.Fatal(err)
}
return list
}
*/
func (p *GeoPoint) GetPointsQueryStringWithIn(d int64) string {
return fmt.Sprintf("ST_DWithin(geog::geography, ST_SetSRID(ST_MakePoint(%f, %f),4326)::geography, %d)", p.Lng, p.Lat, d)
}