-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpoint.go
63 lines (53 loc) · 1.39 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
package datum
import (
"database/sql/driver"
"errors"
"fmt"
"github.com/twpayne/go-geom"
"github.com/twpayne/go-geom/encoding/ewkb"
"github.com/volatiletech/null/convert"
)
// Point is a PostGIS point.
type Point struct {
SRID int
Lng float64
Lat float64
}
// NewPoint creates a new point.
func NewPoint(srid int, lng float64, lat float64) Point {
return Point{
SRID: srid,
Lng: lng,
Lat: lat,
}
}
// PointFromVal creates a new point from any value. If the value is nil, the point (0 0) is returned.
func PointFromVal(value interface{}, srid int) (*Point, error) {
point := NewPoint(srid, 0, 0)
var geometryBuffer []byte
convert.ConvertAssign(&geometryBuffer, value)
geometry, err := ewkb.Unmarshal(geometryBuffer)
if err != nil {
// no library seems to understand what PostGIS is giving us so I just return 0, 0
return &point, nil
}
geomPoint, ok := geometry.(*geom.Point)
if !ok {
return nil, errors.New("geometry is not a point")
}
point = NewPoint(srid, geomPoint.Y(), geomPoint.X())
return &point, nil
}
// Scan implements the Scanner interface.
func (p *Point) Scan(value interface{}, srid int) error {
point, err := PointFromVal(value, srid)
if err != nil {
return err
}
*p = *point
return nil
}
// Value implements the driver Value interface.
func (p Point) Value() (driver.Value, error) {
return fmt.Sprintf("SRID=%d;POINT(%f %f)", p.SRID, p.Lng, p.Lat), nil
}