-
-
Notifications
You must be signed in to change notification settings - Fork 197
/
layer.go
243 lines (210 loc) · 5.63 KB
/
layer.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package mvt
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"os"
"strconv"
"strings"
"context"
"github.com/terranodo/tegola"
"github.com/terranodo/tegola/mvt/vector_tile"
)
var simplifyGeometries = true
var simplificationMaxZoom = 10
func init() {
options := strings.ToLower(os.Getenv("TEGOLA_OPTIONS"))
if strings.Contains(options, "dontsimplifygeo") {
simplifyGeometries = false
log.Println("Turning Off Simplification of Geometries.")
}
if strings.Contains(options, "simplifymaxzoom=") {
idx := strings.Index(options, "simplifymaxzoom=")
idx += 16
eidx := strings.IndexAny(options[idx:], ",.\t \n")
if eidx == -1 {
eidx = len(options)
} else {
eidx += idx
}
i, err := strconv.Atoi(options[idx:eidx])
if err != nil {
log.Printf("Did not under the value(%v) for SimplifyMaxZoom sticking with default (%v).", options[idx:eidx], simplificationMaxZoom)
return
}
simplificationMaxZoom = int(i + 1)
log.Printf("Setting SimplifyMaxZoom to %v", int(i))
}
}
// Layer describes a layer in the tile. Each layer can have multiple features
// which describe drawing.
type Layer struct {
// This is the name of the feature, is has to be unique within a tile.
Name string
// The set of features
features []Feature
extent *int // default is 4096
// DontSimplify truns off simplification for this layer.
DontSimplify bool
// MaxSimplificationZoom is the zoom level at which point simplification is turned off. if value is zero Max is set to 14. If you do not want to simplify at any level set DontSimplify to true.
MaxSimplificationZoom uint
}
func valMapToVTileValue(valMap []interface{}) (vt []*vectorTile.Tile_Value) {
for _, v := range valMap {
vt = append(vt, vectorTileValue(v))
}
return vt
}
// VTileLayer returns a vectorTile Tile_Layer object that represents this layer.
func (l *Layer) VTileLayer(ctx context.Context, extent tegola.BoundingBox) (*vectorTile.Tile_Layer, error) {
kmap, vmap, err := keyvalMapsFromFeatures(l.features)
if err != nil {
return nil, err
}
valmap := valMapToVTileValue(vmap)
var features = make([]*vectorTile.Tile_Feature, 0, len(l.features))
for _, f := range l.features {
if ctx.Err() != nil {
return nil, context.Canceled
}
simplify := simplifyGeometries && !l.DontSimplify
if l.MaxSimplificationZoom == 0 {
l.MaxSimplificationZoom = uint(simplificationMaxZoom)
}
simplify = simplify && extent.Z < int(l.MaxSimplificationZoom)
vtf, err := f.VTileFeature(ctx, kmap, vmap, extent, l.Extent(), simplify)
if err != nil {
return nil, fmt.Errorf("Error getting VTileFeature: %v", err)
}
if vtf != nil {
features = append(features, vtf)
}
}
ext := uint32(l.Extent())
version := uint32(l.Version())
vtl := new(vectorTile.Tile_Layer)
vtl.Version = &version
name := l.Name // Need to make a copy of the string.
vtl.Name = &name
vtl.Features = features
vtl.Keys = kmap
vtl.Values = valmap
vtl.Extent = &ext
return vtl, nil
}
//Version is the version of tile spec this layer is from.
func (*Layer) Version() int {
return 2
}
// Extent defaults to 4096
func (l *Layer) Extent() int {
if l == nil || l.extent == nil {
return 4096
}
return *(l.extent)
}
// SetExtent sets the extent value
func (l *Layer) SetExtent(e int) {
if l == nil {
l = new(Layer)
}
l.extent = &e
}
// Features returns a copy of the features in the layer, use the index of the this
// array to remove any features from the layer
func (l *Layer) Features() (f []Feature) {
if l == nil || l.features == nil {
return nil
}
f = append(f, l.features...)
return f
}
//AddFeatures will add one or more Features to the Layer, if a features ID is a the same as
//Any already in the Layer, it will ignore those features.
//If the id fields is nil, the feature will always be added.
func (l *Layer) AddFeatures(features ...Feature) (skipped bool) {
b := make([]Feature, len(l.features), len(l.features)+len(features))
copy(b, l.features)
l.features = b
FEATURES_LOOP:
for _, f := range features {
if f.ID == nil {
l.features = append(l.features, f)
continue
}
for _, cf := range l.features {
if cf.ID != nil {
continue
}
// We matched, we skip
if *cf.ID == *f.ID {
skipped = true
continue FEATURES_LOOP
}
}
// There were no matches, let's add it to our list.
l.features = append(l.features, f)
}
return skipped
}
//RemoveFeature allows you to remove one or more features, with the provided indexes.
//To figure out the indexes, use the indexs from the Features array.
func (l *Layer) RemoveFeature(idxs ...int) {
var features = make([]Feature, 0, len(l.features))
SKIP:
for i, f := range l.features {
for _, j := range idxs {
if i == j {
continue SKIP
}
}
features = append(features, f)
}
}
func vectorTileValue(i interface{}) *vectorTile.Tile_Value {
tv := new(vectorTile.Tile_Value)
switch t := i.(type) {
default:
buff := new(bytes.Buffer)
err := binary.Write(buff, binary.BigEndian, t)
// We are going to ignore the value and return an empty TileValue
if err == nil {
tv.XXX_unrecognized = buff.Bytes()
}
case string:
tv.StringValue = &t
case fmt.Stringer:
str := t.String()
tv.StringValue = &str
case bool:
tv.BoolValue = &t
case int8:
intv := int64(t)
tv.SintValue = &intv
case int16:
intv := int64(t)
tv.SintValue = &intv
case int32:
intv := int64(t)
tv.SintValue = &intv
case int64:
tv.IntValue = &t
case uint8:
intv := int64(t)
tv.SintValue = &intv
case uint16:
intv := int64(t)
tv.SintValue = &intv
case uint32:
intv := int64(t)
tv.SintValue = &intv
case uint64:
tv.UintValue = &t
case float32:
tv.FloatValue = &t
case float64:
tv.DoubleValue = &t
} // switch
return tv
}