/
feature.go
102 lines (85 loc) · 2.55 KB
/
feature.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
package geojson
import (
"encoding/json"
"fmt"
"github.com/paulmach/orb"
)
// A Feature corresponds to GeoJSON feature object
type Feature struct {
ID interface{} `json:"id,omitempty"`
Type string `json:"type"`
BBox BBox `json:"bbox,omitempty"`
Geometry orb.Geometry `json:"geometry"`
Properties Properties `json:"properties"`
}
// NewFeature creates and initializes a GeoJSON feature given the required attributes.
func NewFeature(geometry orb.Geometry) *Feature {
return &Feature{
Type: "Feature",
Geometry: geometry,
Properties: make(map[string]interface{}),
}
}
// Point implements the orb.Pointer interface so that Features can be used
// with quadtrees. The point returned is the center of the Bound of the geometry.
// To represent the geometry with another point you must create a wrapper type.
func (f *Feature) Point() orb.Point {
return f.Geometry.Bound().Center()
}
var _ orb.Pointer = &Feature{}
// MarshalJSON converts the feature object into the proper JSON.
// It will handle the encoding of all the child geometries.
// Alternately one can call json.Marshal(f) directly for the same result.
func (f Feature) MarshalJSON() ([]byte, error) {
jf := &jsonFeature{
ID: f.ID,
Type: "Feature",
Properties: f.Properties,
BBox: f.BBox,
Geometry: NewGeometry(f.Geometry),
}
if len(jf.Properties) == 0 {
jf.Properties = nil
}
return json.Marshal(jf)
}
// UnmarshalFeature decodes the data into a GeoJSON feature.
// Alternately one can call json.Unmarshal(f) directly for the same result.
func UnmarshalFeature(data []byte) (*Feature, error) {
f := &Feature{}
err := json.Unmarshal(data, f)
if err != nil {
return nil, err
}
return f, nil
}
// UnmarshalJSON handles the correct unmarshalling of the data
// into the orb.Geometry types.
func (f *Feature) UnmarshalJSON(data []byte) error {
jf := &jsonFeature{}
err := json.Unmarshal(data, &jf)
if err != nil {
return err
}
if jf.Type != "Feature" {
return fmt.Errorf("geojson: not a feature: type=%s", jf.Type)
}
if jf.Geometry == nil || jf.Geometry.Coordinates == nil {
return ErrInvalidGeometry
}
*f = Feature{
ID: jf.ID,
Type: jf.Type,
Properties: jf.Properties,
BBox: jf.BBox,
Geometry: jf.Geometry.Coordinates,
}
return nil
}
type jsonFeature struct {
ID interface{} `json:"id,omitempty"`
Type string `json:"type"`
BBox BBox `json:"bbox,omitempty"`
Geometry *Geometry `json:"geometry"`
Properties Properties `json:"properties"`
}