-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
436 lines (412 loc) · 20.3 KB
/
index.html
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Building a national tile set</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/webmapper.css">
<!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="lib/css/monokai.css">
<style>
.leaflet-control-container {
display: none !important;
}
</style>
<!-- Printing and PDF exports -->
<script>
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match(/print-pdf/gi) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName('head')[0].appendChild(link);
</script>
</head>
<body>
<div class="reveal">
<div class="slides">
<section data-background-iframe="./cartiqo/">
<h1>Building a national vector tile set</h1>
<br />
<h2>by: Steven Ottens - <a href="//twitter.com/stvno" style="font-weight: normal; color: #333333"> @stvno</a>
</h2>
<br />
<h2><a style="font-weight: normal; color: #333333"
href="https://webmapper.github.io/foss4g2019/">webmapper.github.io/foss4g2019</a></h2>
<img data-src="img/foss4glogo.png"/>
</section>
<section data-background-image="img/webmapperbkg.png" style="color:#eeeeec; text-shadow: 0px 0px 4px #333333">
<h3 style="color:#eeeeec; text-shadow: 2px 2px 4px #333333">Webmapper</h3>
<h4 style="color:#eeeeec; text-shadow: 2px 2px 4px #333333 ">Utrecht, the Netherlands</h4>
<br />
<br />
<br />
<br />
<p class="fragment fade-up">Data - Design - Technology</p>
</section>
<section>
<section data-background-image="img/utrecht.jpg"><h2 style="color:#eeeeec; text-shadow: 0px 0px 4px #333333">background</h2></section>
<section data-transition="fade" data-background-image="img/top25.jpg">
<h2 style="color:#333333; margin-top: -25vh;">1:25 000</h2>
</section>
<section data-transition="fade" data-background-image="img/top50.jpg">
<h2 style="color:#333333; margin-top: -25vh;">1:50 000</h2>
</section>
<section data-background-iframe="./brt/" data-background-interactive style="text-align: left">
<p class="fragment slide">1:1000 0000</p>
<p class="fragment slide">1:500 0000</p>
<p class="fragment slide">1:250 0000</p>
<p class="fragment slide">1:100 0000</p>
<p class="fragment slide">1:50 0000</p>
<p class="fragment slide">1:10 0000</p>
<p class="fragment slide">large scale topography</p>
</section>
<section data-background-image="img/data.png">
<h1 style="color: #eeeeec; text-shadow: 2px 2px 4px #333333; ">Lots of Data</h1>
</section>
<section data-background-iframe="https://data.amsterdam.nl/data/?modus=kaart">
<h1 style="color: #41382f; text-shadow: 2px 2px 4px #eeeeec; opacity:0.9;">Beautiful maps</h1>
</section>
<section data-background-iframe="bgt/bgt.map"></section>
</section>
<section data-background-iframe="./cartiqobeeld/">
<div style="display: flex; align-items: center">
<div style="font-family: 'cartiqo'; font-size: 100px; color: #eeeeec; min-width:70%">cartiqo</div>
<div>
<p class="fragment" style=" font-size: 50px; color: #eeeeec">Fast</p>
<p class="fragment " style=" font-size: 50px; color: #eeeeec">Simple</p>
<p class="fragment " style=" font-size: 50px; color: #eeeeec">Accurate</p>
<p class="fragment " style=" font-size: 50px; color: #eeeeec">Consistent</p>
</div>
</div>
</section>
<section>
<section data-background-image="img/6colors.gif">
<div>
<h3>Six Color Map</h3>
</div>
<div class=" fragment " style="text-align:left;text-shadow: 1px 1px 4px #eeeeec"">
<p >water</p>
<p >natural</p>
<p >rural</p>
<p >urban</p>
<p >roads</p>
<p >labels</p>
</div>
</section>
<section>
<h3>Consistency</h3>
<img class=" fragment fade" width="200px" data-src="img/nature5.png" /><img class="fragment fade"
width="200px" data-src="img/nature11.png" /><img class="fragment fade" width="200px"
data-src="img/nature16.png" />
<p class="fragment fade">across zoom levels</p>
<p class="fragment fade">across source data</p>
</section>
<section data-transition="slide-in fade-out">
<h3> 11³ </h3>
<img style="max-height:600px; margin-top:-60px" data-src="img/cartiqo.png" />
</section>
<section data-transition="fade-in slide-out">
<h3> 11³ </h3>
<img style="max-height:600px; margin-top:-60px" data-src="img/cartiqo-builtup.png" />
</section>
<section data-background-image="img/kaart.png" data-transition="slide-in fade-out">
<h3><span style="opacity:0">Lots of </span>Beautiful maps</h3>
</section>
<section data-background-image="img/kaarten.png" data-transition="fade-in fade-out">
<h3>Lots of Beautiful maps</h3>
<div style="float: right;position: fixed; top: 60vh; right: 1vw; height: 10vh;"><a
style="font-size:20px; color:#eeeeec; text-shadow:1px 1px 3px #333333"
href="https://www.instagram.com/webmappery/">instagram.com/webmappery</a></span>
</section>
<section data-background-image="img/less.png" data-transition="fade-in fade-out">
<div
style="display: flex;justify-content: space-around;align-items: center; color: #eeeeec; font-size: 60px;">
<div>rendering<br />maps</div>
<div style="display: flex;justify-content:space-between;align-items: center" class="fragment">
<span style="margin-right:20px;">></span>
<div>generating<br />tiles</div>
</div>
<div style="display: flex;justify-content:space-between;align-items: center" class="fragment">
<span style="margin-right:20px;">></span>
<div>importing<br />data</div>
</div>
</div>
</section>
<section data-transition="slide-in fade-out">
<h3>Simple datamodel</h3>
<img style="height:40vh" data-src="img/cartiqo_schema.png" /><br />
<a href="https://github.com/webmapper/cartiqo-documentation">github.com/webmapper/cartiqo-documentation</a>
</section>
<section data-transition="fade-in slide-out">
<h3>Simple datamodel</h3>
<img style="height:40vh" data-src="img/openzoomstack.png" /><br />
<a href="https://www.ordnancesurvey.co.uk/business-and-government/products/os-open-zoomstack.html">Open
Zoomstack - Ordnance Survey</a>
</section>
<section>
<h3>Map the source data</h3>
<pre><code data-trim data-noescape>
----------NATURAL--------------------
--high
INSERT INTO cartiqo.natural_5_6_uo (type, geom, originalId)
select 'high', st_multi(geometrie_vlak_3857), gml_id
from top1000.terrein where typelandgebruik = 'bos';
--bare
INSERT INTO cartiqo.natural_5_6_uo (type, geom, originalId)
select 'bare', st_multi(geometrie_vlak_3857), gml_id
from top1000.terrein where typelandgebruik = 'zand';
</code></pre>
<p class="fragment fade">flatten your data</p>
<p class="fragment fade">storage is cheap!</p>
<span class="fragment fade" style="border:solid 2px #317581;border-radius: 4px;padding:10px;"><b>⁂</b> SQL is
your friend <b>⁂</b></span>
</section>
<section data-background-image="img/hard.gif">
</section>
</section>
<section>
<section data-background-image="img/not quite.gif">
<p class="fragment" style="font-size: 60px; color: #eeeeec;font-weight: 100">not quite</p>
</section>
<section data-background-image="img/update.jpg"
style="font-size: 60px; color: #eeeeec;text-shadow: 1px 1px 4px #333333; font-weight: bold">
<div style="display: flex; justify-content: center;align-items: center">
<div style="text-align: right">
<div class=""> generating</div>
<div class="fragment">serving</div>
<div class="fragment">updating</div>
<div class="fragment">tiles</div>
</div>
</div>
</section>
</section>
<section>
<section style="font-size: 60px; color: #333333;text-shadow: 1px 1px 4px #eeeeec; ">
<p>pick a vector tile engine</p>
<p class="fragment" style="font-weight: bold">☑ postgres backend</p>
<span class="fragment" style="text-decoration: line-through">tippecanoe</span>
<span class="fragment" style="text-decoration: line-through">osm2vectortiles</span>
<p style="font-weight: bold" class="fragment">☑ S3 cache</p>
<span class="fragment" style="text-decoration: line-through">geoserver</span>
<span class="fragment" style="text-decoration: line-through">t-rex</span>
<span class="fragment" style="text-decoration: line-through">tilelive</span><br />
<span class="fragment fade" style="border:solid 2px #317581;border-radius: 4px;padding:10px;"><b>⁂</b> <A
href="https://tegola.io/">Tegola</A> is your friend <b>⁂</b></span>
</section>
<section>
<h3>Mapproxy inspired</h3>
<p class="fragment">providers - maps - caches</p>
<pre class="fragment fade"><code data-trim data-noescape>
[[providers.layers]]
name = "natural56"
sql = "SELECT ... ST_AsBinary(geom) AS geom
FROM cartiqo.natural_5_6 WHERE geom && !BBOX!"
</code></pre>
<pre class="fragment fade"><code data-trim data-noescape>
[[maps.layers]]
provider_layer = "cartiqo.natural56"
min_zoom = 2
max_zoom = 6
name = "natural"
</code></pre>
<pre class="fragment fade"><code data-trim data-noescape>
[cache]
type="s3"
bucket="mybucket"
</code></pre>
</section>
<section>
<h3>Prepare for tiles</h3>
<pre class="fragment fade"><code data-trim data-noescape>
CREATE TABLE cartiqo.natural_5_6 AS
SELECT * FROM cartiqo.natural_5_6_uo
ORDER BY ST_GeoHash(ST_Transform(ST_Envelope(geom),4326),10)
COLLATE "C";
CREATE INDEX cartiqo_natural_5_6_geohash
ON cartiqo.natural_5_6
(ST_GeoHash(ST_Transform(ST_Envelope(geom),4326),10));
CLUSTER cartiqo.natural_5_6 USING cartiqo_natural_5_6_geohash;
CREATE INDEX cartiqo_natural_5_6_geom
ON cartiqo.natural_5_6 USING gist (geom);
</code></pre>
<span class="fragment fade" style="border:solid 2px #317581;border-radius: 4px;padding:10px;"><b>⁂</b> <A
href="http://www.paulnorman.ca/blog/2016/05/improve-your-st-geohash-sorting-with-these-three-simple-tricks/">Paul
Norman</A> is your friend <b>⁂</b></span>
</section>
<section>
<pre><code data-noescape>
$ ./tegola cache seed --bounds "4.5,50.0,5.5,52.0" --concurrency 12
</code></pre>
</section>
</section>
<section data-transition="slide-in fade-out">
<section data-background-image="img/fast.gif"
style="font-weight: bold;font-size: 60px; color: #333333;text-shadow: 1px 1px 4px #eeeeec; ">
<p>Did I mention fast?</p>
</section>
<section>
<div style="display: flex; align-items: center">
<img data-src="img/slow.gif" />
<div class="fragment fade" style="margin:40px; font-size: 60px">S3 != fast</div>
</div>
</section>
<section>
<h3>Content Delivery Network (CDN)</h3>
<quote>A [...] CDN is a geographically distributed network of proxy servers and their data centers.
The goal is to provide high availability and <b>high performance</b> by distributing the service spatially
relative to end-users. </quote>
<p style="text-align: right; font-style: italic"><a
href="https://en.wikipedia.org/wiki/Content_delivery_network">wikipedia</a></p>
</section>
<section data-transition="slide-in fade-out">
<h3 style="display: flex; justify-content: center">
<div>🚀</div>
<div style="margin:0px 15px"> Enables web speed </div>
<div style="transform: scale(-1, 1);">🚀</div>
</h3>
<p class="fragment fade">gzip encoding <span class="fragment">- native tegola</span></p>
<p class="fragment fade">cache-headers <span class="fragment">- tegola config</span></p>
<pre class="fragment fade"><code data-trim data-noescape>
access_control_list="public-read"
cache_control="public, max-age=604800"
</code></pre>
<p class="fragment fade">multiple subdomains <span class="fragment">- CDN config</span></p>
<div><img height="250px" class="fade fragment" data-src="img/headers.png" /><img class="fade fragment"
height="250px" data-src="img/timing.png" /></div>
</section>
</section>
<section data-transition="fade-in fade-out">
<section data-background-iframe="./update/index.html" data-transition="fade-in fade-out">
<p class="fragment" style="font-size: 60px; color: #eeeeec;font-weight: 100; margin-bottom: 300px">let's talk
updates</p>
</section>
<section data-transition="fade-in fade-out">
<pre><code data-noescape>
$ ./tegola cache seed --bounds "4.5,50.0,5.5,52.0" --overwrite
</code></pre>
</section>
<section data-transition="fade-in fade-out">
<pre style="width:100%"><code data-noescape>
$ ./tegola cache seed --tile-list="list.txt" --max-zoom 15 --overwrite
</code></pre>
</section>
<section data-background-image="img/data.png">
<h1 style="color: #eeeeec; text-shadow: 2px 2px 4px #333333; ">Lots of Data</h1>
</section>
<section data-background-image="img/datawrangling.gif">
<h1 style="color: #eeeeec; text-shadow: 2px 2px 4px #333333; ">updating be like</h1>
</section>
<section data-background-iframe="https://nlextract.nl">
<h1 class="fragment"
style="color: #eeeeec; text-shadow: 1px 1px 8px #333333; line-height:600px;background-blend-mode: multiply; background-color: rgba(236, 114, 0, 0.8)">
We cheat</h1>
</section>
<section>
<h1 style="text-transform: lowercase;color:#333"><span style="color:#ff882a">nl</span>extract</h1>
<p class="fragment fade">government data, but:</p>
<p class="fragment fade">as postgres dumps</p>
<p class="fragment fade">with stable URLs</p>
<p class="fragment fade">& still regularly updated</p>
<div class="fragment" style="margin-top:60px;">Open Source!</div>
</section>
<section data-background-image="img/automate.gif">
<h1 style="color:#333;text-transform: none">Automate</h1>
<pre class="fragment fade"><code data-trim data-noescape>
curl --silent --head "$url" # some fancy bash follows here
if [ $theirdate -gt $ourdate ]; then
# there is a newer file on the server, lets run the scripts
./run.sh $url $theirs
else
echo "No newer version of "$file"; currently at "$theirs
fi
</code></pre>
<pre class="fragment fade"><code data-trim data-noescape>
----------NATURAL--------------------
--high
INSERT INTO cartiqo.natural_5_6_uo (type, geom, originalId)
select 'high', st_multi(geometrie_vlak_3857), gml_id
from top1000.terrein where typelandgebruik = 'bos';
--bare
INSERT INTO cartiqo.natural_5_6_uo (type, geom, originalId)
select 'bare', st_multi(geometrie_vlak_3857), gml_id
from top1000.terrein where typelandgebruik = 'zand';
</code></pre>
</section>
<section>
<h3>update steps</h3>
<ol>
<li class="fragment fade">check for new open data</li>
<li class="fragment fade">import new open data</li>
<li class="fragment fade">map data to datamodel</li>
<li class="fragment fade"><code data-trim data-noescape>seed --overwrite</code></li>
<li class="fragment fade">optional bust CDN</li>
</ol>
</section>
</section>
<section style="text-align: left">
<h3>To wrap up:</h3>
<p>1. create a sensible datamodel</p>
<p>2. map your source data to that model</p>
<p>3. use postgis for datawrangling</p>
<p>4. generate tiles with Tegola</p>
<p>5. store them on an object store (S3)</p>
<p>6. serve them through a CDN</p>
<p>bonus: get your own <span style="color:black !important; font-weight: bold"><a style="color:#ff882a"
href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">[ISO 3166-1 alpha-2]</a>extract</span> project</p>
</section>
<section data-background-image="img/questions.png">
<div
style="height:600px; display: flex;flex-direction: column;justify-content: space-between">
<img style="background: none;width:100px;align-self: flex-end" data-src="img/webmapper_logo.svg" />
<div style="color:#ff882a; font-size:40px; font-weight: bold;margin-right:60px;text-shadow: 1px 1px 4px #333;margin-bottom: 60px">
Questions?</div>
<div style="display: flex;justify-content: space-between; font-size:smaller; font-weight: bold"><a style="font-weight: bold; color: #eeeeec;text-shadow: 1px 1px 4px #333"
href="https://webmapper.github.io/foss4g2019/">webmapper.github.io/foss4g2019</a>
<a style="font-weight: bold; color: #eeeeec; text-shadow: 1px 1px 4px #333" href="https://twitter.com/stvno">@stvno</a></div>
</div>
</section>
<section data-transition="fade-out">
<h3>Pop quiz:</h3>
<p class="fragment slide">Feature type: "barren terrain"</p>
<p class="fragment slide">Physical appearance: "open pavement"</p>
<p style="opacity:0">Hardening formed by related elements of <b>limited</b> dimensions, such as, for example,
clinkers and tiles.
</section>
<section data-transition="fade" data-background-image="img/straat.jpeg">
<h3>Pop quiz:</h3>
<p style="color:#eeeeec; text-shadow: 2px 2px 4px #333333">Feature type: "barren terrain"</p>
<p style="color:#eeeeec; text-shadow: 2px 2px 4px #333333">Physical appearance: "open pavement"</p>
<p class="fragment slide" style="color:#eeeeec; text-shadow: 2px 2px 4px #333333; font-style: italic">
Hardening formed by
related elements of <b>limited</b> dimensions, such as, for example, clinkers and tiles.
</section>
</div>
</div>
<script src="js/reveal.js"></script>
<script>
// More info about config & dependencies:
// - https://github.com/hakimel/reveal.js#configuration
// - https://github.com/hakimel/reveal.js#dependencies
Reveal.initialize({
history: true,
dependencies: [{
src: 'plugin/markdown/marked.js'
},
{
src: 'plugin/markdown/markdown.js'
},
{
src: 'plugin/notes/notes.js',
async: true
},
{
src: 'plugin/highlight/highlight.js',
async: true
}
]
});
</script>
</body>
</html>