-
Notifications
You must be signed in to change notification settings - Fork 106
/
multipoint.go
160 lines (142 loc) · 3.79 KB
/
multipoint.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package geom
// A MultiPoint is a collection of Points.
type MultiPoint struct {
// To represent an MultiPoint that allows EMPTY elements, e.g.
// MULTIPOINT ( EMPTY, POINT(1.0 1.0), EMPTY), we have to allow
// record ends. If there is an empty point, ends[i] == ends[i-1].
geom2
}
// NewMultiPoint returns a new, empty, MultiPoint.
func NewMultiPoint(layout Layout) *MultiPoint {
return NewMultiPointFlat(layout, nil)
}
// NewMultiPointFlatOption represents an option that can be passed into
// NewMultiPointFlat.
type NewMultiPointFlatOption func(*MultiPoint)
// NewMultiPointFlatOptionWithEnds allows passing ends to NewMultiPointFlat,
// which allows the representation of empty points.
func NewMultiPointFlatOptionWithEnds(ends []int) NewMultiPointFlatOption {
return func(mp *MultiPoint) {
mp.ends = ends
}
}
// NewMultiPointFlat returns a new MultiPoint with the given flat coordinates.
// Assumes no points are empty by default. Use `NewMultiPointFlatOptionWithEnds`
// to specify empty points.
func NewMultiPointFlat(
layout Layout, flatCoords []float64, opts ...NewMultiPointFlatOption,
) *MultiPoint {
g := new(MultiPoint)
g.layout = layout
g.stride = layout.Stride()
g.flatCoords = flatCoords
for _, opt := range opts {
opt(g)
}
// If no ends are provided, assume all points are non empty.
if g.ends == nil && len(g.flatCoords) > 0 {
numCoords := 0
if g.stride > 0 {
numCoords = len(flatCoords) / g.stride
}
g.ends = make([]int, numCoords)
for i := 0; i < numCoords; i++ {
g.ends[i] = (i + 1) * g.stride
}
}
return g
}
// Area returns the area of g, i.e. zero.
func (g *MultiPoint) Area() float64 {
return 0
}
// Clone returns a deep copy.
func (g *MultiPoint) Clone() *MultiPoint {
return deriveCloneMultiPoint(g)
}
// Length returns zero.
func (g *MultiPoint) Length() float64 {
return 0
}
// MustSetCoords sets the coordinates and panics on any error.
func (g *MultiPoint) MustSetCoords(coords []Coord) *MultiPoint {
Must(g.SetCoords(coords))
return g
}
// Coord returns the ith coord of g.
func (g *MultiPoint) Coord(i int) Coord {
before := 0
if i > 0 {
before = g.ends[i-1]
}
if g.ends[i] == before {
return nil
}
return g.flatCoords[before:g.ends[i]]
}
// SetCoords sets the coordinates.
func (g *MultiPoint) SetCoords(coords []Coord) (*MultiPoint, error) {
g.flatCoords = nil
g.ends = nil
for _, c := range coords {
if c != nil {
var err error
g.flatCoords, err = deflate0(g.flatCoords, c, g.stride)
if err != nil {
return nil, err
}
}
g.ends = append(g.ends, len(g.flatCoords))
}
return g, nil
}
// Coords unpacks and returns all of g's coordinates.
func (g *MultiPoint) Coords() []Coord {
coords1 := make([]Coord, len(g.ends))
offset := 0
prevEnd := 0
for i, end := range g.ends {
if end != prevEnd {
coords1[i] = inflate0(g.flatCoords, offset, offset+g.stride, g.stride)
offset += g.stride
}
prevEnd = end
}
return coords1
}
// NumCoords returns the number of coordinates in g.
func (g *MultiPoint) NumCoords() int {
return len(g.ends)
}
// SetSRID sets the SRID of g.
func (g *MultiPoint) SetSRID(srid int) *MultiPoint {
g.srid = srid
return g
}
// NumPoints returns the number of Points.
func (g *MultiPoint) NumPoints() int {
return len(g.ends)
}
// Point returns the ith Point.
func (g *MultiPoint) Point(i int) *Point {
coord := g.Coord(i)
if coord == nil {
return NewPointEmpty(g.layout)
}
return NewPointFlat(g.layout, coord)
}
// Push appends a point.
func (g *MultiPoint) Push(p *Point) error {
if p.layout != g.layout {
return ErrLayoutMismatch{Got: p.layout, Want: g.layout}
}
if !p.Empty() {
g.flatCoords = append(g.flatCoords, p.flatCoords...)
}
g.ends = append(g.ends, len(g.flatCoords))
return nil
}
// Swap swaps the values of g and g2.
func (g *MultiPoint) Swap(g2 *MultiPoint) {
*g, *g2 = *g2, *g
}