tileserver-gl-light 5.1.1 → 5.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -1
- package/changelog_for_version.md +1 -1
- package/docs/endpoints.rst +2 -0
- package/package.json +1 -1
- package/public/templates/data.tmpl +6 -0
- package/public/templates/index.tmpl +2 -2
- package/src/serve_data.js +28 -75
- package/src/serve_light.js +4 -0
- package/src/serve_rendered.js +73 -1
- package/src/server.js +13 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# tileserver-gl changelog
|
|
2
2
|
|
|
3
|
+
## 5.1.3
|
|
4
|
+
* Fix SIGHUP (broken since 5.1.x) (https://github.com/maptiler/tileserver-gl/pull/1452) by @okimiko
|
|
5
|
+
|
|
6
|
+
## 5.1.2
|
|
7
|
+
* Fix broken light (invalid use of heavy dependencies) (https://github.com/maptiler/tileserver-gl/pull/1449) by @okimiko
|
|
8
|
+
|
|
3
9
|
## 5.1.1
|
|
4
|
-
* Fix wrong node version in Docker image (https://github.com/maptiler/tileserver-gl/pull/
|
|
10
|
+
* Fix wrong node version in Docker image (https://github.com/maptiler/tileserver-gl/pull/1442) by @acalcutt
|
|
5
11
|
|
|
6
12
|
## 5.1.0
|
|
7
13
|
* Update recommended node to v22 + Update docker images to use node 22 (https://github.com/maptiler/tileserver-gl/pull/1438) by @acalcutt
|
package/changelog_for_version.md
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
* Fix
|
|
1
|
+
* Fix SIGHUP (broken since 5.1.x) (https://github.com/maptiler/tileserver-gl/pull/1452) by @okimiko
|
|
2
2
|
|
package/docs/endpoints.rst
CHANGED
|
@@ -108,6 +108,8 @@ Source data
|
|
|
108
108
|
|
|
109
109
|
* the result will be a json object like ``{"z":7,"x":68,"y":45,"red":134,"green":66,"blue":0,"latitude":11.84069,"longitude":46.04798,"elevation":1602}``
|
|
110
110
|
|
|
111
|
+
* The elevation api is not available in the ``tileserver-gl-light`` version.
|
|
112
|
+
|
|
111
113
|
Static files
|
|
112
114
|
===========
|
|
113
115
|
* Static files are served at ``/files/{filename}``
|
package/package.json
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
<link rel="stylesheet" type="text/css" href="{{public_url}}maplibre-gl-inspect.css{{&key_query}}" />
|
|
10
10
|
<script src="{{public_url}}maplibre-gl.js{{&key_query}}"></script>
|
|
11
11
|
<script src="{{public_url}}maplibre-gl-inspect.js{{&key_query}}"></script>
|
|
12
|
+
{{^is_light}}
|
|
12
13
|
<script src="{{public_url}}elevation-control.js{{&key_query}}"></script>
|
|
14
|
+
{{/is_light}}
|
|
13
15
|
<style>
|
|
14
16
|
body {background:#fff;color:#333;font-family:Arial, sans-serif;}
|
|
15
17
|
{{^is_terrain}}
|
|
@@ -21,7 +23,9 @@
|
|
|
21
23
|
h1 {position:absolute;top:5px;right:0;width:240px;margin:0;line-height:20px;font-size:20px;}
|
|
22
24
|
#layerList {position:absolute;top:35px;right:0;bottom:0;width:240px;overflow:auto;}
|
|
23
25
|
#layerList div div {width:15px;height:15px;display:inline-block;}
|
|
26
|
+
{{^is_light}}
|
|
24
27
|
.maplibre-ctrl-elevation { padding-left: 5px; padding-right: 5px; }
|
|
28
|
+
{{/is_light}}
|
|
25
29
|
</style>
|
|
26
30
|
{{/use_maplibre}}
|
|
27
31
|
{{^use_maplibre}}
|
|
@@ -135,11 +139,13 @@
|
|
|
135
139
|
})
|
|
136
140
|
);
|
|
137
141
|
|
|
142
|
+
{{^is_light}}
|
|
138
143
|
map.addControl(
|
|
139
144
|
new ElevationInfoControl({
|
|
140
145
|
url: "{{public_url}}data/{{id}}/elevation/{z}/{x}/{y}"
|
|
141
146
|
})
|
|
142
147
|
);
|
|
148
|
+
{{/is_light}}
|
|
143
149
|
{{/is_terrain}}
|
|
144
150
|
{{^is_terrain}}
|
|
145
151
|
|
|
@@ -124,9 +124,9 @@
|
|
|
124
124
|
{{/is_vector}}
|
|
125
125
|
{{^is_vector}}
|
|
126
126
|
<a class="btn" href="{{public_url}}data/{{@key}}/{{&../key_query}}{{viewer_hash}}">View</a>
|
|
127
|
-
{{#
|
|
127
|
+
{{#is_terrain}}
|
|
128
128
|
<a class="btn" href="{{public_url}}data/preview/{{@key}}/{{&../key_query}}{{viewer_hash}}">Preview Terrain</a>
|
|
129
|
-
{{/
|
|
129
|
+
{{/is_terrain}}
|
|
130
130
|
{{/is_vector}}
|
|
131
131
|
</div>
|
|
132
132
|
</div>
|
package/src/serve_data.js
CHANGED
|
@@ -8,8 +8,6 @@ import express from 'express';
|
|
|
8
8
|
import Pbf from 'pbf';
|
|
9
9
|
import { VectorTile } from '@mapbox/vector-tile';
|
|
10
10
|
import SphericalMercator from '@mapbox/sphericalmercator';
|
|
11
|
-
import { Image, createCanvas } from 'canvas';
|
|
12
|
-
import sharp from 'sharp';
|
|
13
11
|
|
|
14
12
|
import {
|
|
15
13
|
fixTileJSONCenter,
|
|
@@ -21,6 +19,20 @@ import { getPMtilesInfo, openPMtiles } from './pmtiles_adapter.js';
|
|
|
21
19
|
import { gunzipP, gzipP } from './promises.js';
|
|
22
20
|
import { openMbTilesWrapper } from './mbtiles_wrapper.js';
|
|
23
21
|
|
|
22
|
+
import fs from 'node:fs';
|
|
23
|
+
import { fileURLToPath } from 'url';
|
|
24
|
+
const packageJson = JSON.parse(
|
|
25
|
+
fs.readFileSync(
|
|
26
|
+
path.dirname(fileURLToPath(import.meta.url)) + '/../package.json',
|
|
27
|
+
'utf8',
|
|
28
|
+
),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const isLight = packageJson.name.slice(-6) === '-light';
|
|
32
|
+
const serve_rendered = (
|
|
33
|
+
await import(`${!isLight ? `./serve_rendered.js` : `./serve_light.js`}`)
|
|
34
|
+
).serve_rendered;
|
|
35
|
+
|
|
24
36
|
export const serve_data = {
|
|
25
37
|
/**
|
|
26
38
|
* Initializes the serve_data module.
|
|
@@ -246,79 +258,20 @@ export const serve_data = {
|
|
|
246
258
|
if (fetchTile == null) return res.status(204).send();
|
|
247
259
|
|
|
248
260
|
let data = fetchTile.data;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
siny = Math.min(Math.max(siny, -0.9999), 0.9999);
|
|
264
|
-
const xWorld = TILE_SIZE * (0.5 + long / 360);
|
|
265
|
-
const yWorld =
|
|
266
|
-
TILE_SIZE *
|
|
267
|
-
(0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI));
|
|
268
|
-
|
|
269
|
-
const scale = 1 << zoom;
|
|
270
|
-
|
|
271
|
-
const xTile = Math.floor((xWorld * scale) / TILE_SIZE);
|
|
272
|
-
const yTile = Math.floor((yWorld * scale) / TILE_SIZE);
|
|
273
|
-
|
|
274
|
-
const xPixel = Math.floor(xWorld * scale) - xTile * TILE_SIZE;
|
|
275
|
-
const yPixel = Math.floor(yWorld * scale) - yTile * TILE_SIZE;
|
|
276
|
-
if (
|
|
277
|
-
xPixel < 0 ||
|
|
278
|
-
yPixel < 0 ||
|
|
279
|
-
xPixel >= TILE_SIZE ||
|
|
280
|
-
yPixel >= TILE_SIZE
|
|
281
|
-
) {
|
|
282
|
-
return reject('Out of bounds Pixel');
|
|
283
|
-
}
|
|
284
|
-
const imgdata = context.getImageData(xPixel, yPixel, 1, 1);
|
|
285
|
-
const red = imgdata.data[0];
|
|
286
|
-
const green = imgdata.data[1];
|
|
287
|
-
const blue = imgdata.data[2];
|
|
288
|
-
let elevation;
|
|
289
|
-
if (encoding === 'mapbox') {
|
|
290
|
-
elevation = -10000 + (red * 256 * 256 + green * 256 + blue) * 0.1;
|
|
291
|
-
} else if (encoding === 'terrarium') {
|
|
292
|
-
elevation = red * 256 + green + blue / 256 - 32768;
|
|
293
|
-
} else {
|
|
294
|
-
elevation = 'invalid encoding';
|
|
295
|
-
}
|
|
296
|
-
resolve(
|
|
297
|
-
res.status(200).send({
|
|
298
|
-
z: zoom,
|
|
299
|
-
x: xy[0],
|
|
300
|
-
y: xy[1],
|
|
301
|
-
red,
|
|
302
|
-
green,
|
|
303
|
-
blue,
|
|
304
|
-
latitude: lat,
|
|
305
|
-
longitude: long,
|
|
306
|
-
elevation,
|
|
307
|
-
}),
|
|
308
|
-
);
|
|
309
|
-
};
|
|
310
|
-
image.onerror = (err) => reject(err);
|
|
311
|
-
if (format === 'webp') {
|
|
312
|
-
try {
|
|
313
|
-
const img = await sharp(data).toFormat('png').toBuffer();
|
|
314
|
-
image.src = img;
|
|
315
|
-
} catch (err) {
|
|
316
|
-
reject(err);
|
|
317
|
-
}
|
|
318
|
-
} else {
|
|
319
|
-
image.src = data;
|
|
320
|
-
}
|
|
321
|
-
});
|
|
261
|
+
var param = {
|
|
262
|
+
long: bbox[0],
|
|
263
|
+
lat: bbox[1],
|
|
264
|
+
encoding,
|
|
265
|
+
format,
|
|
266
|
+
tile_size: TILE_SIZE,
|
|
267
|
+
z: zoom,
|
|
268
|
+
x: xy[0],
|
|
269
|
+
y: xy[1],
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
res
|
|
273
|
+
.status(200)
|
|
274
|
+
.send(await serve_rendered.getTerrainElevation(data, param));
|
|
322
275
|
} catch (err) {
|
|
323
276
|
return res
|
|
324
277
|
.status(500)
|
package/src/serve_light.js
CHANGED
|
@@ -6,4 +6,8 @@ export const serve_rendered = {
|
|
|
6
6
|
init: (options, repo, programOpts) => {},
|
|
7
7
|
add: (options, repo, params, id, programOpts, dataResolver) => {},
|
|
8
8
|
remove: (repo, id) => {},
|
|
9
|
+
getTerrainElevation: (data, param) => {
|
|
10
|
+
param['elevation'] = 'not supported in light';
|
|
11
|
+
return param;
|
|
12
|
+
},
|
|
9
13
|
};
|
package/src/serve_rendered.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// This happens on ARM:
|
|
8
8
|
// > terminate called after throwing an instance of 'std::runtime_error'
|
|
9
9
|
// > what(): Cannot read GLX extensions.
|
|
10
|
-
import 'canvas';
|
|
10
|
+
import { Image, createCanvas } from 'canvas';
|
|
11
11
|
import '@maplibre/maplibre-gl-native';
|
|
12
12
|
//
|
|
13
13
|
// SECTION END
|
|
@@ -1458,4 +1458,76 @@ export const serve_rendered = {
|
|
|
1458
1458
|
}
|
|
1459
1459
|
delete repo[id];
|
|
1460
1460
|
},
|
|
1461
|
+
|
|
1462
|
+
/**
|
|
1463
|
+
* Get the elevation of terrain tile data by rendering it to a canvas image
|
|
1464
|
+
* @param {object} data The background color (or empty string for transparent).
|
|
1465
|
+
* @param {object} param Required parameters (coordinates e.g.)
|
|
1466
|
+
* @returns {object}
|
|
1467
|
+
*/
|
|
1468
|
+
getTerrainElevation: async function (data, param) {
|
|
1469
|
+
return await new Promise(async (resolve, reject) => {
|
|
1470
|
+
const image = new Image();
|
|
1471
|
+
image.onload = async () => {
|
|
1472
|
+
const canvas = createCanvas(param['tile_size'], param['tile_size']);
|
|
1473
|
+
const context = canvas.getContext('2d');
|
|
1474
|
+
context.drawImage(image, 0, 0);
|
|
1475
|
+
|
|
1476
|
+
// calculate pixel coordinate of tile,
|
|
1477
|
+
// see https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
|
|
1478
|
+
let siny = Math.sin((param['lat'] * Math.PI) / 180);
|
|
1479
|
+
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
|
|
1480
|
+
// about a third of a tile past the edge of the world tile.
|
|
1481
|
+
siny = Math.min(Math.max(siny, -0.9999), 0.9999);
|
|
1482
|
+
const xWorld = param['tile_size'] * (0.5 + param['long'] / 360);
|
|
1483
|
+
const yWorld =
|
|
1484
|
+
param['tile_size'] *
|
|
1485
|
+
(0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI));
|
|
1486
|
+
|
|
1487
|
+
const scale = 1 << param['z'];
|
|
1488
|
+
|
|
1489
|
+
const xTile = Math.floor((xWorld * scale) / param['tile_size']);
|
|
1490
|
+
const yTile = Math.floor((yWorld * scale) / param['tile_size']);
|
|
1491
|
+
|
|
1492
|
+
const xPixel = Math.floor(xWorld * scale) - xTile * param['tile_size'];
|
|
1493
|
+
const yPixel = Math.floor(yWorld * scale) - yTile * param['tile_size'];
|
|
1494
|
+
if (
|
|
1495
|
+
xPixel < 0 ||
|
|
1496
|
+
yPixel < 0 ||
|
|
1497
|
+
xPixel >= param['tile_size'] ||
|
|
1498
|
+
yPixel >= param['tile_size']
|
|
1499
|
+
) {
|
|
1500
|
+
return reject('Out of bounds Pixel');
|
|
1501
|
+
}
|
|
1502
|
+
const imgdata = context.getImageData(xPixel, yPixel, 1, 1);
|
|
1503
|
+
const red = imgdata.data[0];
|
|
1504
|
+
const green = imgdata.data[1];
|
|
1505
|
+
const blue = imgdata.data[2];
|
|
1506
|
+
let elevation;
|
|
1507
|
+
if (param['encoding'] === 'mapbox') {
|
|
1508
|
+
elevation = -10000 + (red * 256 * 256 + green * 256 + blue) * 0.1;
|
|
1509
|
+
} else if (param['encoding'] === 'terrarium') {
|
|
1510
|
+
elevation = red * 256 + green + blue / 256 - 32768;
|
|
1511
|
+
} else {
|
|
1512
|
+
elevation = 'invalid encoding';
|
|
1513
|
+
}
|
|
1514
|
+
param['elevation'] = elevation;
|
|
1515
|
+
param['red'] = red;
|
|
1516
|
+
param['green'] = green;
|
|
1517
|
+
param['blue'] = blue;
|
|
1518
|
+
resolve(param);
|
|
1519
|
+
};
|
|
1520
|
+
image.onerror = (err) => reject(err);
|
|
1521
|
+
if (param['format'] === 'webp') {
|
|
1522
|
+
try {
|
|
1523
|
+
const img = await sharp(data).toFormat('png').toBuffer();
|
|
1524
|
+
image.src = img;
|
|
1525
|
+
} catch (err) {
|
|
1526
|
+
reject(err);
|
|
1527
|
+
}
|
|
1528
|
+
} else {
|
|
1529
|
+
image.src = data;
|
|
1530
|
+
}
|
|
1531
|
+
});
|
|
1532
|
+
},
|
|
1461
1533
|
};
|
package/src/server.js
CHANGED
|
@@ -24,13 +24,12 @@ import {
|
|
|
24
24
|
} from './utils.js';
|
|
25
25
|
|
|
26
26
|
import { fileURLToPath } from 'url';
|
|
27
|
-
const
|
|
28
|
-
const __dirname = path.dirname(__filename);
|
|
27
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
28
|
const packageJson = JSON.parse(
|
|
30
29
|
fs.readFileSync(__dirname + '/../package.json', 'utf8'),
|
|
31
30
|
);
|
|
32
|
-
|
|
33
31
|
const isLight = packageJson.name.slice(-6) === '-light';
|
|
32
|
+
|
|
34
33
|
const serve_rendered = (
|
|
35
34
|
await import(`${!isLight ? `./serve_rendered.js` : `./serve_light.js`}`)
|
|
36
35
|
).serve_rendered;
|
|
@@ -575,11 +574,14 @@ async function start(opts) {
|
|
|
575
574
|
tileJSON.encoding === 'terrarium' ||
|
|
576
575
|
tileJSON.encoding === 'mapbox'
|
|
577
576
|
) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
577
|
+
if (!isLight) {
|
|
578
|
+
data.elevation_link = getTileUrls(
|
|
579
|
+
req,
|
|
580
|
+
tileJSON.tiles,
|
|
581
|
+
`data/${id}/elevation`,
|
|
582
|
+
)[0];
|
|
583
|
+
}
|
|
584
|
+
data.is_terrain = true;
|
|
583
585
|
}
|
|
584
586
|
if (center) {
|
|
585
587
|
const centerPx = mercator.px([center[0], center[1]], center[2]);
|
|
@@ -698,6 +700,7 @@ async function start(opts) {
|
|
|
698
700
|
is_terrain: is_terrain,
|
|
699
701
|
is_terrainrgb: data.tileJSON.encoding === 'mapbox',
|
|
700
702
|
terrain_encoding: data.tileJSON.encoding,
|
|
703
|
+
is_light: isLight,
|
|
701
704
|
};
|
|
702
705
|
});
|
|
703
706
|
|
|
@@ -772,8 +775,8 @@ export async function server(opts) {
|
|
|
772
775
|
console.log(`Caught signal ${signal}, refreshing`);
|
|
773
776
|
console.log('Stopping server and reloading config');
|
|
774
777
|
|
|
775
|
-
running.server.shutdown(() => {
|
|
776
|
-
const restarted = start(opts);
|
|
778
|
+
running.server.shutdown(async () => {
|
|
779
|
+
const restarted = await start(opts);
|
|
777
780
|
running.server = restarted.server;
|
|
778
781
|
running.app = restarted.app;
|
|
779
782
|
});
|