forked from dewski/spatial
-
Notifications
You must be signed in to change notification settings - Fork 0
/
point.go
89 lines (75 loc) · 1.54 KB
/
point.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
// Based on https://github.com/jinzhu/gorm/issues/142
package spatial
import (
"bytes"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"fmt"
)
type Point struct {
Lng float64 `json:"lng"`
Lat float64 `json:"lat"`
}
func (p *Point) String() string {
return fmt.Sprintf("SRID=4326;POINT(%v %v)", p.Lng, p.Lat)
}
func (p *Point) Scan(val interface{}) error {
b, err := hex.DecodeString(string(val.([]uint8)))
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
}
func (p Point) Value() (driver.Value, error) {
return p.String(), nil
}
type NullPoint struct {
Point Point
Valid bool
}
func (np *NullPoint) Scan(val interface{}) error {
if val == nil {
np.Point, np.Valid = Point{}, false
return nil
}
point := &Point{}
err := point.Scan(val)
if err != nil {
np.Point, np.Valid = Point{}, false
return nil
}
np.Point = Point{
Lat: point.Lat,
Lng: point.Lng,
}
np.Valid = true
return nil
}
func (np NullPoint) Value() (driver.Value, error) {
if !np.Valid {
return nil, nil
}
return np.Point.Value()
}