maplibre-gl 3.3.1 → 3.4.1
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/README.md +1 -1
- package/dist/maplibre-gl-csp-worker.js +1 -1
- package/dist/maplibre-gl-csp-worker.js.map +1 -1
- package/dist/maplibre-gl-csp.js +1 -1
- package/dist/maplibre-gl-csp.js.map +1 -1
- package/dist/maplibre-gl-dev.js +430 -128
- package/dist/maplibre-gl-dev.js.map +1 -1
- package/dist/maplibre-gl.d.ts +18 -9
- package/dist/maplibre-gl.js +4 -4
- package/dist/maplibre-gl.js.map +1 -1
- package/package.json +41 -41
- package/src/data/dem_data.test.ts +120 -165
- package/src/data/dem_data.ts +38 -18
- package/src/render/glyph_manager.test.ts +10 -9
- package/src/render/glyph_manager.ts +17 -10
- package/src/source/image_source.test.ts +17 -24
- package/src/source/raster_dem_tile_source.ts +36 -11
- package/src/source/raster_dem_tile_worker_source.ts +9 -26
- package/src/source/raster_tile_source.test.ts +1 -1
- package/src/source/raster_tile_source.ts +1 -1
- package/src/source/terrain_source_cache.test.ts +1 -1
- package/src/source/vector_tile_source.test.ts +1 -1
- package/src/source/vector_tile_worker_source.test.ts +45 -1
- package/src/source/vector_tile_worker_source.ts +19 -6
- package/src/source/worker_source.ts +6 -2
- package/src/style/load_glyph_range.test.ts +6 -8
- package/src/style/load_sprite.test.ts +48 -71
- package/src/style/style.test.ts +19 -49
- package/src/style/style.ts +3 -0
- package/src/style/style_glyph.ts +4 -3
- package/src/style/style_layer/line_style_layer.test.ts +50 -0
- package/src/style/style_layer/line_style_layer.ts +8 -4
- package/src/symbol/quads.ts +4 -2
- package/src/ui/handler/scroll_zoom.ts +6 -0
- package/src/ui/handler_manager.ts +2 -1
- package/src/ui/map.test.ts +17 -0
- package/src/ui/map.ts +1 -0
- package/src/ui/marker.test.ts +25 -0
- package/src/ui/marker.ts +8 -1
- package/src/util/ajax.test.ts +1 -1
- package/src/util/image_request.test.ts +1 -1
- package/src/util/offscreen_canvas_distorted.test.ts +13 -0
- package/src/util/offscreen_canvas_distorted.ts +39 -0
- package/src/util/test/util.ts +12 -0
- package/src/util/util.test.ts +171 -1
- package/src/util/util.ts +150 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "maplibre-gl",
|
|
3
3
|
"description": "BSD licensed community fork of mapbox-gl, a WebGL interactive maps library",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.4.1",
|
|
5
5
|
"main": "dist/maplibre-gl.js",
|
|
6
6
|
"style": "dist/maplibre-gl.css",
|
|
7
7
|
"license": "BSD-3-Clause",
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"@mapbox/unitbezier": "^0.0.1",
|
|
21
21
|
"@mapbox/vector-tile": "^1.3.1",
|
|
22
22
|
"@mapbox/whoots-js": "^3.1.0",
|
|
23
|
-
"@maplibre/maplibre-gl-style-spec": "^19.3.
|
|
24
|
-
"@types/geojson": "^7946.0.
|
|
23
|
+
"@maplibre/maplibre-gl-style-spec": "^19.3.2",
|
|
24
|
+
"@types/geojson": "^7946.0.11",
|
|
25
25
|
"@types/mapbox__point-geometry": "^0.1.2",
|
|
26
|
-
"@types/mapbox__vector-tile": "^1.3.
|
|
27
|
-
"@types/pbf": "^3.0.
|
|
28
|
-
"@types/supercluster": "^7.1.
|
|
26
|
+
"@types/mapbox__vector-tile": "^1.3.1",
|
|
27
|
+
"@types/pbf": "^3.0.3",
|
|
28
|
+
"@types/supercluster": "^7.1.1",
|
|
29
29
|
"earcut": "^2.2.4",
|
|
30
30
|
"geojson-vt": "^3.2.1",
|
|
31
31
|
"gl-matrix": "^3.4.3",
|
|
@@ -42,56 +42,56 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@mapbox/mapbox-gl-rtl-text": "^0.2.3",
|
|
44
44
|
"@mapbox/mvt-fixtures": "^3.10.0",
|
|
45
|
-
"@rollup/plugin-commonjs": "^25.0.
|
|
46
|
-
"@rollup/plugin-json": "^6.0.
|
|
47
|
-
"@rollup/plugin-node-resolve": "^15.2.
|
|
48
|
-
"@rollup/plugin-replace": "^5.0.
|
|
49
|
-
"@rollup/plugin-strip": "^3.0.
|
|
50
|
-
"@rollup/plugin-terser": "^0.4.
|
|
51
|
-
"@rollup/plugin-typescript": "^11.1.
|
|
52
|
-
"@types/benchmark": "^2.1.
|
|
45
|
+
"@rollup/plugin-commonjs": "^25.0.5",
|
|
46
|
+
"@rollup/plugin-json": "^6.0.1",
|
|
47
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
48
|
+
"@rollup/plugin-replace": "^5.0.3",
|
|
49
|
+
"@rollup/plugin-strip": "^3.0.3",
|
|
50
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
51
|
+
"@rollup/plugin-typescript": "^11.1.5",
|
|
52
|
+
"@types/benchmark": "^2.1.3",
|
|
53
53
|
"@types/cssnano": "^5.0.0",
|
|
54
|
-
"@types/d3": "^7.4.
|
|
55
|
-
"@types/diff": "^5.0.
|
|
56
|
-
"@types/earcut": "^2.1.
|
|
57
|
-
"@types/eslint": "^8.44.
|
|
58
|
-
"@types/gl": "^6.0.
|
|
54
|
+
"@types/d3": "^7.4.1",
|
|
55
|
+
"@types/diff": "^5.0.5",
|
|
56
|
+
"@types/earcut": "^2.1.2",
|
|
57
|
+
"@types/eslint": "^8.44.3",
|
|
58
|
+
"@types/gl": "^6.0.3",
|
|
59
59
|
"@types/glob": "^8.1.0",
|
|
60
60
|
"@types/jest": "^29.5.3",
|
|
61
|
-
"@types/jsdom": "^21.1.
|
|
62
|
-
"@types/minimist": "^1.2.
|
|
61
|
+
"@types/jsdom": "^21.1.3",
|
|
62
|
+
"@types/minimist": "^1.2.3",
|
|
63
63
|
"@types/murmurhash-js": "^1.0.4",
|
|
64
|
-
"@types/nise": "^1.4.
|
|
65
|
-
"@types/node": "^20.
|
|
66
|
-
"@types/offscreencanvas": "^2019.7.
|
|
64
|
+
"@types/nise": "^1.4.2",
|
|
65
|
+
"@types/node": "^20.8.3",
|
|
66
|
+
"@types/offscreencanvas": "^2019.7.1",
|
|
67
67
|
"@types/pixelmatch": "^5.2.4",
|
|
68
|
-
"@types/pngjs": "^6.0.
|
|
69
|
-
"@types/react": "^18.2.
|
|
70
|
-
"@types/react-dom": "^18.2.
|
|
71
|
-
"@types/request": "^2.48.
|
|
68
|
+
"@types/pngjs": "^6.0.2",
|
|
69
|
+
"@types/react": "^18.2.25",
|
|
70
|
+
"@types/react-dom": "^18.2.11",
|
|
71
|
+
"@types/request": "^2.48.9",
|
|
72
72
|
"@types/shuffle-seed": "^1.1.0",
|
|
73
73
|
"@types/window-or-global": "^1.0.4",
|
|
74
|
-
"@typescript-eslint/eslint-plugin": "^6.4
|
|
75
|
-
"@typescript-eslint/parser": "^6.4
|
|
76
|
-
"address": "^
|
|
74
|
+
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
75
|
+
"@typescript-eslint/parser": "^6.7.4",
|
|
76
|
+
"address": "^2.0.1",
|
|
77
77
|
"benchmark": "^2.1.4",
|
|
78
78
|
"canvas": "^2.11.2",
|
|
79
79
|
"cssnano": "^6.0.1",
|
|
80
80
|
"d3": "^7.8.5",
|
|
81
81
|
"d3-queue": "^3.0.7",
|
|
82
|
-
"devtools-protocol": "^0.0.
|
|
82
|
+
"devtools-protocol": "^0.0.1206220",
|
|
83
83
|
"diff": "^5.1.0",
|
|
84
84
|
"dts-bundle-generator": "^8.0.1",
|
|
85
|
-
"eslint": "^8.
|
|
85
|
+
"eslint": "^8.51.0",
|
|
86
86
|
"eslint-config-mourner": "^3.0.0",
|
|
87
87
|
"eslint-plugin-html": "^7.1.0",
|
|
88
88
|
"eslint-plugin-import": "^2.28.1",
|
|
89
|
-
"eslint-plugin-jest": "^27.2
|
|
89
|
+
"eslint-plugin-jest": "^27.4.2",
|
|
90
90
|
"eslint-plugin-react": "^7.33.2",
|
|
91
91
|
"eslint-plugin-tsdoc": "0.2.17",
|
|
92
|
-
"expect": "^29.
|
|
92
|
+
"expect": "^29.7.0",
|
|
93
93
|
"gl": "^6.0.2",
|
|
94
|
-
"glob": "^10.3.
|
|
94
|
+
"glob": "^10.3.10",
|
|
95
95
|
"is-builtin-module": "^3.2.1",
|
|
96
96
|
"jest": "^29.6.2",
|
|
97
97
|
"jest-canvas-mock": "^2.5.2",
|
|
@@ -107,14 +107,14 @@
|
|
|
107
107
|
"pdf-merger-js": "^4.3.0",
|
|
108
108
|
"pixelmatch": "^5.3.0",
|
|
109
109
|
"pngjs": "^7.0.0",
|
|
110
|
-
"postcss": "^8.4.
|
|
110
|
+
"postcss": "^8.4.31",
|
|
111
111
|
"postcss-cli": "^10.1.0",
|
|
112
112
|
"postcss-inline-svg": "^6.0.0",
|
|
113
113
|
"pretty-bytes": "^6.1.1",
|
|
114
|
-
"puppeteer": "^21.
|
|
114
|
+
"puppeteer": "^21.3.8",
|
|
115
115
|
"react": "^18.2.0",
|
|
116
116
|
"react-dom": "^18.2.0",
|
|
117
|
-
"rollup": "^
|
|
117
|
+
"rollup": "^4.0.2",
|
|
118
118
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
|
119
119
|
"rw": "^1.3.3",
|
|
120
120
|
"semver": "^7.5.4",
|
|
@@ -126,10 +126,10 @@
|
|
|
126
126
|
"ts-jest": "^29.1.1",
|
|
127
127
|
"ts-node": "^10.9.1",
|
|
128
128
|
"tslib": "^2.6.2",
|
|
129
|
-
"typedoc": "^0.
|
|
129
|
+
"typedoc": "^0.25.2",
|
|
130
130
|
"typedoc-plugin-markdown": "^3.16.0",
|
|
131
131
|
"typedoc-plugin-missing-exports": "^2.1.0",
|
|
132
|
-
"typescript": "^5.
|
|
132
|
+
"typescript": "^5.2.2"
|
|
133
133
|
},
|
|
134
134
|
"overrides": {
|
|
135
135
|
"postcss-inline-svg": {
|
|
@@ -47,179 +47,111 @@ describe('DEMData', () => {
|
|
|
47
47
|
new DEMData('0', imageData0, 'otherEncoding' as any);
|
|
48
48
|
|
|
49
49
|
expect(spyOnWarnConsole).toHaveBeenCalledTimes(1);
|
|
50
|
-
expect(spyOnWarnConsole.mock.calls).toEqual([['\"otherEncoding\" is not a valid encoding type. Valid types include \"mapbox\" and \"
|
|
50
|
+
expect(spyOnWarnConsole.mock.calls).toEqual([['\"otherEncoding\" is not a valid encoding type. Valid types include \"mapbox\", \"terrarium\" and \"custom\".']]);
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
for (let y = -1; y < 5; y++) {
|
|
64
|
-
if (dem0.get(x, y) === -65536) {
|
|
65
|
-
nonempty = false;
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
55
|
+
function testDEMBorderRegion(dem: DEMData) {
|
|
56
|
+
return () => {
|
|
57
|
+
let nonempty = true;
|
|
58
|
+
for (let x = -1; x < 5; x++) {
|
|
59
|
+
for (let y = -1; y < 5; y++) {
|
|
60
|
+
if (dem.get(x, y) === -65536) {
|
|
61
|
+
nonempty = false;
|
|
62
|
+
break;
|
|
68
63
|
}
|
|
69
64
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
65
|
+
}
|
|
66
|
+
expect(nonempty).toBeTruthy();
|
|
67
|
+
|
|
68
|
+
let verticalBorderMatch = true;
|
|
69
|
+
for (const x of [-1, 4]) {
|
|
70
|
+
for (let y = 0; y < 4; y++) {
|
|
71
|
+
if (dem.get(x, y) !== dem.get(x < 0 ? x + 1 : x - 1, y)) {
|
|
72
|
+
verticalBorderMatch = false;
|
|
73
|
+
break;
|
|
79
74
|
}
|
|
80
75
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
76
|
+
}
|
|
77
|
+
expect(verticalBorderMatch).toBeTruthy();
|
|
78
|
+
|
|
79
|
+
// horizontal borders empty
|
|
80
|
+
let horizontalBorderMatch = true;
|
|
81
|
+
for (const y of [-1, 4]) {
|
|
82
|
+
for (let x = 0; x < 4; x++) {
|
|
83
|
+
if (dem.get(x, y) !== dem.get(x, y < 0 ? y + 1 : y - 1)) {
|
|
84
|
+
horizontalBorderMatch = false;
|
|
85
|
+
break;
|
|
91
86
|
}
|
|
92
87
|
}
|
|
93
|
-
|
|
88
|
+
}
|
|
89
|
+
expect(horizontalBorderMatch).toBeTruthy();
|
|
94
90
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
91
|
+
expect(dem.get(-1, 4) === dem.get(0, 3)).toBeTruthy();
|
|
92
|
+
expect(dem.get(4, 4) === dem.get(3, 3)).toBeTruthy();
|
|
93
|
+
expect(dem.get(-1, -1) === dem.get(0, 0)).toBeTruthy();
|
|
94
|
+
expect(dem.get(4, -1) === dem.get(3, 0)).toBeTruthy();
|
|
95
|
+
};
|
|
96
|
+
}
|
|
100
97
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
function testDEMBackfill(dem0: DEMData, dem1: DEMData) {
|
|
99
|
+
return () => {
|
|
100
|
+
dem0.backfillBorder(dem1, -1, 0);
|
|
101
|
+
for (let y = 0; y < 4; y++) {
|
|
104
102
|
// dx = -1, dy = 0, so the left edge of dem1 should equal the right edge of dem0
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
expect(dem0.get(-1, y) === dem1.get(3, y)).toBeTruthy();
|
|
104
|
+
}
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
dem0.backfillBorder(dem1, 0, -1);
|
|
107
|
+
for (let x = 0; x < 4; x++) {
|
|
108
|
+
expect(dem0.get(x, -1) === dem1.get(x, 3)).toBeTruthy();
|
|
109
|
+
}
|
|
112
110
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
dem0.backfillBorder(dem1, 1, 0);
|
|
112
|
+
for (let y = 0; y < 4; y++) {
|
|
113
|
+
expect(dem0.get(4, y) === dem1.get(0, y)).toBeTruthy();
|
|
114
|
+
}
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
dem0.backfillBorder(dem1, 0, 1);
|
|
117
|
+
for (let x = 0; x < 4; x++) {
|
|
118
|
+
expect(dem0.get(x, 4) === dem1.get(x, 0)).toBeTruthy();
|
|
119
|
+
}
|
|
122
120
|
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
dem0.backfillBorder(dem1, -1, 1);
|
|
122
|
+
expect(dem0.get(-1, 4) === dem1.get(3, 0)).toBeTruthy();
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
dem0.backfillBorder(dem1, 1, 1);
|
|
125
|
+
expect(dem0.get(4, 4) === dem1.get(0, 0)).toBeTruthy();
|
|
128
126
|
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
dem0.backfillBorder(dem1, -1, -1);
|
|
128
|
+
expect(dem0.get(-1, -1) === dem1.get(3, 3)).toBeTruthy();
|
|
131
129
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
dem0.backfillBorder(dem1, 1, -1);
|
|
131
|
+
expect(dem0.get(4, -1) === dem1.get(0, 3)).toBeTruthy();
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
describe('DEMData#backfillBorder with encoding', () => {
|
|
136
|
+
describe('mabox encoding', () => {
|
|
137
|
+
const dem0 = new DEMData('0', createMockImage(4, 4), 'mapbox');
|
|
138
|
+
const dem1 = new DEMData('1', createMockImage(4, 4), 'mapbox');
|
|
139
|
+
|
|
140
|
+
test('border region is initially populated with neighboring data', testDEMBorderRegion(dem0));
|
|
141
|
+
test('backfillBorder correctly populates borders with neighboring data', testDEMBackfill(dem0, dem1));
|
|
135
142
|
});
|
|
136
143
|
|
|
137
144
|
describe('terrarium encoding', () => {
|
|
138
145
|
const dem0 = new DEMData('0', createMockImage(4, 4), 'terrarium');
|
|
139
146
|
const dem1 = new DEMData('1', createMockImage(4, 4), 'terrarium');
|
|
140
147
|
|
|
141
|
-
test('border region is initially populated with neighboring data', ()
|
|
142
|
-
|
|
143
|
-
for (let x = -1; x < 5; x++) {
|
|
144
|
-
for (let y = -1; y < 5; y++) {
|
|
145
|
-
if (dem0.get(x, y) === -65536) {
|
|
146
|
-
nonempty = false;
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
expect(nonempty).toBeTruthy();
|
|
152
|
-
|
|
153
|
-
let verticalBorderMatch = true;
|
|
154
|
-
for (const x of [-1, 4]) {
|
|
155
|
-
for (let y = 0; y < 4; y++) {
|
|
156
|
-
if (dem0.get(x, y) !== dem0.get(x < 0 ? x + 1 : x - 1, y)) {
|
|
157
|
-
verticalBorderMatch = false;
|
|
158
|
-
break;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
expect(verticalBorderMatch).toBeTruthy();
|
|
163
|
-
|
|
164
|
-
// horizontal borders empty
|
|
165
|
-
let horizontalBorderMatch = true;
|
|
166
|
-
for (const y of [-1, 4]) {
|
|
167
|
-
for (let x = 0; x < 4; x++) {
|
|
168
|
-
if (dem0.get(x, y) !== dem0.get(x, y < 0 ? y + 1 : y - 1)) {
|
|
169
|
-
horizontalBorderMatch = false;
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
expect(horizontalBorderMatch).toBeTruthy();
|
|
175
|
-
|
|
176
|
-
expect(dem0.get(-1, 4) === dem0.get(0, 3)).toBeTruthy();
|
|
177
|
-
expect(dem0.get(4, 4) === dem0.get(3, 3)).toBeTruthy();
|
|
178
|
-
expect(dem0.get(-1, -1) === dem0.get(0, 0)).toBeTruthy();
|
|
179
|
-
expect(dem0.get(4, -1) === dem0.get(3, 0)).toBeTruthy();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
test('backfillBorder correctly populates borders with neighboring data', () => {
|
|
183
|
-
dem0.backfillBorder(dem1, -1, 0);
|
|
184
|
-
for (let y = 0; y < 4; y++) {
|
|
185
|
-
// dx = -1, dy = 0, so the left edge of dem1 should equal the right edge of dem0
|
|
186
|
-
expect(dem0.get(-1, y) === dem1.get(3, y)).toBeTruthy();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
dem0.backfillBorder(dem1, 0, -1);
|
|
190
|
-
for (let x = 0; x < 4; x++) {
|
|
191
|
-
expect(dem0.get(x, -1) === dem1.get(x, 3)).toBeTruthy();
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
dem0.backfillBorder(dem1, 1, 0);
|
|
195
|
-
for (let y = 0; y < 4; y++) {
|
|
196
|
-
expect(dem0.get(4, y) === dem1.get(0, y)).toBeTruthy();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
dem0.backfillBorder(dem1, 0, 1);
|
|
200
|
-
for (let x = 0; x < 4; x++) {
|
|
201
|
-
expect(dem0.get(x, 4) === dem1.get(x, 0)).toBeTruthy();
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
dem0.backfillBorder(dem1, -1, 1);
|
|
205
|
-
expect(dem0.get(-1, 4) === dem1.get(3, 0)).toBeTruthy();
|
|
206
|
-
|
|
207
|
-
dem0.backfillBorder(dem1, 1, 1);
|
|
208
|
-
expect(dem0.get(4, 4) === dem1.get(0, 0)).toBeTruthy();
|
|
209
|
-
|
|
210
|
-
dem0.backfillBorder(dem1, -1, -1);
|
|
211
|
-
expect(dem0.get(-1, -1) === dem1.get(3, 3)).toBeTruthy();
|
|
212
|
-
|
|
213
|
-
dem0.backfillBorder(dem1, 1, -1);
|
|
214
|
-
expect(dem0.get(4, -1) === dem1.get(0, 3)).toBeTruthy();
|
|
215
|
-
});
|
|
148
|
+
test('border region is initially populated with neighboring data', testDEMBorderRegion(dem0));
|
|
149
|
+
test('backfillBorder correctly populates borders with neighboring data', testDEMBackfill(dem0, dem1));
|
|
216
150
|
});
|
|
217
151
|
});
|
|
218
152
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const imageData0 = createMockImage(4, 4);
|
|
222
|
-
const dem0 = new DEMData('0', imageData0, 'mapbox');
|
|
153
|
+
function testSerialization(dem0: DEMData, redFactor: number, greenFactor: number, blueFactor: number, baseShift: number) {
|
|
154
|
+
return () => {
|
|
223
155
|
const serialized = serialize(dem0);
|
|
224
156
|
|
|
225
157
|
// calculate min/max values
|
|
@@ -239,7 +171,10 @@ describe('DEMData is correctly serialized and deserialized', () => {
|
|
|
239
171
|
dim: 4,
|
|
240
172
|
stride: 6,
|
|
241
173
|
data: dem0.data,
|
|
242
|
-
|
|
174
|
+
redFactor,
|
|
175
|
+
greenFactor,
|
|
176
|
+
blueFactor,
|
|
177
|
+
baseShift,
|
|
243
178
|
max,
|
|
244
179
|
min,
|
|
245
180
|
});
|
|
@@ -247,36 +182,56 @@ describe('DEMData is correctly serialized and deserialized', () => {
|
|
|
247
182
|
const transferrables = [];
|
|
248
183
|
serialize(dem0, transferrables);
|
|
249
184
|
expect(new Uint32Array(transferrables[0])).toEqual(dem0.data);
|
|
250
|
-
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
251
187
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const dem0 = new DEMData('0', imageData0, 'terrarium');
|
|
188
|
+
function testDeserialization(dem0: DEMData) {
|
|
189
|
+
return () => {
|
|
255
190
|
const serialized = serialize(dem0);
|
|
256
191
|
|
|
257
192
|
const deserialized = deserialize(serialized);
|
|
258
193
|
expect(deserialized).toEqual(dem0);
|
|
259
|
-
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
describe('DEMData is correctly serialized and deserialized', () => {
|
|
198
|
+
const mapboxDEM = new DEMData('0', createMockImage(4, 4), 'mapbox');
|
|
199
|
+
const terrariumDEM = new DEMData('0', createMockImage(4, 4), 'terrarium');
|
|
200
|
+
const customDEM = new DEMData('0', createMockImage(4, 4), 'custom', 1.0, 2.0, 3.0, 4.0);
|
|
201
|
+
test('serialized - mapbox', testSerialization(mapboxDEM, 6553.6, 25.6, 0.1, 10000));
|
|
202
|
+
test('serialized - terrarium', testSerialization(terrariumDEM, 256.0, 1.0, 1.0 / 256.0, 32768.0));
|
|
203
|
+
test('serialized - custom', testSerialization(customDEM, 1.0, 2.0, 3.0, 4.0));
|
|
204
|
+
|
|
205
|
+
test('deserialized - mapbox', testDeserialization(mapboxDEM));
|
|
206
|
+
test('deserialized - terrarium', testDeserialization(terrariumDEM));
|
|
207
|
+
test('deserialized - custom', testDeserialization(customDEM));
|
|
260
208
|
});
|
|
261
209
|
|
|
262
210
|
describe('UnpackVector is correctly returned', () => {
|
|
263
|
-
test('terrarium and
|
|
264
|
-
const
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
expect(
|
|
271
|
-
expect(dem2.getUnpackVector()).toEqual([6553.6, 25.6, 0.1, 10000.0]);
|
|
211
|
+
test('terrarium, mapbox and custom', () => {
|
|
212
|
+
const mapboxDEM = new DEMData('0', createMockImage(4, 4), 'mapbox');
|
|
213
|
+
const terrariumDEM = new DEMData('0', createMockImage(4, 4), 'terrarium');
|
|
214
|
+
const customDEM = new DEMData('0', createMockImage(4, 4), 'custom', 1.0, 2.0, 3.0, 4.0);
|
|
215
|
+
|
|
216
|
+
expect(terrariumDEM.getUnpackVector()).toEqual([256.0, 1.0, 1.0 / 256.0, 32768.0]);
|
|
217
|
+
expect(mapboxDEM.getUnpackVector()).toEqual([6553.6, 25.6, 0.1, 10000.0]);
|
|
218
|
+
expect(customDEM.getUnpackVector()).toEqual([1.0, 2.0, 3.0, 4.0]);
|
|
272
219
|
});
|
|
273
220
|
});
|
|
274
221
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const imageData = createMockImage(4, 4);
|
|
278
|
-
const dem = new DEMData('0', imageData, 'terrarium');
|
|
279
|
-
|
|
222
|
+
function testGetPixels(dem: DEMData, imageData: RGBAImage) {
|
|
223
|
+
return () => {
|
|
280
224
|
expect(dem.getPixels()).toEqual(imageData);
|
|
281
|
-
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
describe('DEMData#getImage', () => {
|
|
229
|
+
const imageData = createMockImage(4, 4);
|
|
230
|
+
const mapboxDEM = new DEMData('0', imageData, 'terrarium');
|
|
231
|
+
const terrariumDEM = new DEMData('0', imageData, 'terrarium');
|
|
232
|
+
const customDEM = new DEMData('0', imageData, 'terrarium');
|
|
233
|
+
|
|
234
|
+
test('Image is correctly returned - mapbox', testGetPixels(mapboxDEM, imageData));
|
|
235
|
+
test('Image is correctly returned - terrarium', testGetPixels(terrariumDEM, imageData));
|
|
236
|
+
test('Image is correctly returned - custom', testGetPixels(customDEM, imageData));
|
|
282
237
|
});
|
package/src/data/dem_data.ts
CHANGED
|
@@ -13,6 +13,8 @@ import {register} from '../util/web_worker_transfer';
|
|
|
13
13
|
// surrounding pixel values to compute the slope at that pixel, and we cannot accurately calculate the slope at pixels on a
|
|
14
14
|
// tile's edge without backfilling from neighboring tiles.
|
|
15
15
|
|
|
16
|
+
export type DEMEncoding = 'mapbox' | 'terrarium' | 'custom'
|
|
17
|
+
|
|
16
18
|
export class DEMData {
|
|
17
19
|
uid: string;
|
|
18
20
|
data: Uint32Array;
|
|
@@ -20,21 +22,48 @@ export class DEMData {
|
|
|
20
22
|
dim: number;
|
|
21
23
|
min: number;
|
|
22
24
|
max: number;
|
|
23
|
-
|
|
25
|
+
redFactor: number;
|
|
26
|
+
greenFactor: number;
|
|
27
|
+
blueFactor: number;
|
|
28
|
+
baseShift: number;
|
|
24
29
|
|
|
25
30
|
// RGBAImage data has uniform 1px padding on all sides: square tile edge size defines stride
|
|
26
31
|
// and dim is calculated as stride - 2.
|
|
27
|
-
constructor(uid: string, data: RGBAImage, encoding:
|
|
32
|
+
constructor(uid: string, data: RGBAImage, encoding: DEMEncoding, redFactor = 1.0, greenFactor = 1.0, blueFactor = 1.0, baseShift = 0.0) {
|
|
28
33
|
this.uid = uid;
|
|
29
34
|
if (data.height !== data.width) throw new RangeError('DEM tiles must be square');
|
|
30
|
-
if (encoding &&
|
|
31
|
-
warnOnce(`"${encoding}" is not a valid encoding type. Valid types include "mapbox" and "
|
|
35
|
+
if (encoding && !['mapbox', 'terrarium', 'custom'].includes(encoding)) {
|
|
36
|
+
warnOnce(`"${encoding}" is not a valid encoding type. Valid types include "mapbox", "terrarium" and "custom".`);
|
|
32
37
|
return;
|
|
33
38
|
}
|
|
34
39
|
this.stride = data.height;
|
|
35
40
|
const dim = this.dim = data.height - 2;
|
|
36
41
|
this.data = new Uint32Array(data.data.buffer);
|
|
37
|
-
|
|
42
|
+
switch (encoding) {
|
|
43
|
+
case 'terrarium':
|
|
44
|
+
// unpacking formula for mapzen terrarium:
|
|
45
|
+
// https://aws.amazon.com/public-datasets/terrain/
|
|
46
|
+
this.redFactor = 256.0;
|
|
47
|
+
this.greenFactor = 1.0;
|
|
48
|
+
this.blueFactor = 1.0 / 256.0;
|
|
49
|
+
this.baseShift = 32768.0;
|
|
50
|
+
break;
|
|
51
|
+
case 'custom':
|
|
52
|
+
this.redFactor = redFactor;
|
|
53
|
+
this.greenFactor = greenFactor;
|
|
54
|
+
this.blueFactor = blueFactor;
|
|
55
|
+
this.baseShift = baseShift;
|
|
56
|
+
break;
|
|
57
|
+
case 'mapbox':
|
|
58
|
+
default:
|
|
59
|
+
// unpacking formula for mapbox.terrain-rgb:
|
|
60
|
+
// https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb
|
|
61
|
+
this.redFactor = 6553.6;
|
|
62
|
+
this.greenFactor = 25.6;
|
|
63
|
+
this.blueFactor = 0.1;
|
|
64
|
+
this.baseShift = 10000.0;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
38
67
|
|
|
39
68
|
// in order to avoid flashing seams between tiles, here we are initially populating a 1px border of pixels around the image
|
|
40
69
|
// with the data of the nearest pixel from the image. this data is eventually replaced when the tile's neighboring
|
|
@@ -70,12 +99,11 @@ export class DEMData {
|
|
|
70
99
|
get(x: number, y: number) {
|
|
71
100
|
const pixels = new Uint8Array(this.data.buffer);
|
|
72
101
|
const index = this._idx(x, y) * 4;
|
|
73
|
-
|
|
74
|
-
return unpack(pixels[index], pixels[index + 1], pixels[index + 2]);
|
|
102
|
+
return this.unpack(pixels[index], pixels[index + 1], pixels[index + 2]);
|
|
75
103
|
}
|
|
76
104
|
|
|
77
105
|
getUnpackVector() {
|
|
78
|
-
return this.
|
|
106
|
+
return [this.redFactor, this.greenFactor, this.blueFactor, this.baseShift];
|
|
79
107
|
}
|
|
80
108
|
|
|
81
109
|
_idx(x: number, y: number) {
|
|
@@ -83,16 +111,8 @@ export class DEMData {
|
|
|
83
111
|
return (y + 1) * this.stride + (x + 1);
|
|
84
112
|
}
|
|
85
113
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb
|
|
89
|
-
return ((r * 256 * 256 + g * 256.0 + b) / 10.0 - 10000.0);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
_unpackTerrarium(r: number, g: number, b: number) {
|
|
93
|
-
// unpacking formula for mapzen terrarium:
|
|
94
|
-
// https://aws.amazon.com/public-datasets/terrain/
|
|
95
|
-
return ((r * 256 + g + b / 256) - 32768.0);
|
|
114
|
+
unpack(r: number, g: number, b: number) {
|
|
115
|
+
return (r * this.redFactor + g * this.greenFactor + b * this.blueFactor - this.baseShift);
|
|
96
116
|
}
|
|
97
117
|
|
|
98
118
|
getPixels() {
|
|
@@ -95,13 +95,13 @@ describe('GlyphManager', () => {
|
|
|
95
95
|
manager.getGlyphs({'Arial Unicode MS': [0x3005]}, (err, glyphs) => {
|
|
96
96
|
expect(err).toBeFalsy();
|
|
97
97
|
expect(glyphs['Arial Unicode MS'][0x3005]).not.toBeNull();
|
|
98
|
-
//Request char from Katakana range (te)
|
|
98
|
+
//Request char from Katakana range (te テ)
|
|
99
99
|
manager.getGlyphs({'Arial Unicode MS': [0x30C6]}, (err, glyphs) => {
|
|
100
100
|
expect(err).toBeFalsy();
|
|
101
101
|
const glyph = glyphs['Arial Unicode MS'][0x30c6];
|
|
102
102
|
//Ensure that te is locally generated.
|
|
103
|
-
expect(glyph.bitmap.height).toBe(
|
|
104
|
-
expect(glyph.bitmap.width).toBe(
|
|
103
|
+
expect(glyph.bitmap.height).toBe(12);
|
|
104
|
+
expect(glyph.bitmap.width).toBe(12);
|
|
105
105
|
done();
|
|
106
106
|
});
|
|
107
107
|
});
|
|
@@ -110,9 +110,10 @@ describe('GlyphManager', () => {
|
|
|
110
110
|
test('GlyphManager generates CJK PBF locally', done => {
|
|
111
111
|
const manager = createGlyphManager('sans-serif');
|
|
112
112
|
|
|
113
|
+
// character 平
|
|
113
114
|
manager.getGlyphs({'Arial Unicode MS': [0x5e73]}, (err, glyphs) => {
|
|
114
115
|
expect(err).toBeFalsy();
|
|
115
|
-
expect(glyphs['Arial Unicode MS'][0x5e73].metrics.advance).toBe(
|
|
116
|
+
expect(glyphs['Arial Unicode MS'][0x5e73].metrics.advance).toBe(0.5);
|
|
116
117
|
done();
|
|
117
118
|
});
|
|
118
119
|
});
|
|
@@ -120,10 +121,10 @@ describe('GlyphManager', () => {
|
|
|
120
121
|
test('GlyphManager generates Katakana PBF locally', done => {
|
|
121
122
|
const manager = createGlyphManager('sans-serif');
|
|
122
123
|
|
|
123
|
-
// Katakana letter te
|
|
124
|
+
// Katakana letter te テ
|
|
124
125
|
manager.getGlyphs({'Arial Unicode MS': [0x30c6]}, (err, glyphs) => {
|
|
125
126
|
expect(err).toBeFalsy();
|
|
126
|
-
expect(glyphs['Arial Unicode MS'][0x30c6].metrics.advance).toBe(
|
|
127
|
+
expect(glyphs['Arial Unicode MS'][0x30c6].metrics.advance).toBe(0.5);
|
|
127
128
|
done();
|
|
128
129
|
});
|
|
129
130
|
});
|
|
@@ -131,10 +132,10 @@ describe('GlyphManager', () => {
|
|
|
131
132
|
test('GlyphManager generates Hiragana PBF locally', done => {
|
|
132
133
|
const manager = createGlyphManager('sans-serif');
|
|
133
134
|
|
|
134
|
-
//Hiragana letter te
|
|
135
|
+
//Hiragana letter te て
|
|
135
136
|
manager.getGlyphs({'Arial Unicode MS': [0x3066]}, (err, glyphs) => {
|
|
136
137
|
expect(err).toBeFalsy();
|
|
137
|
-
expect(glyphs['Arial Unicode MS'][0x3066].metrics.advance).toBe(
|
|
138
|
+
expect(glyphs['Arial Unicode MS'][0x3066].metrics.advance).toBe(0.5);
|
|
138
139
|
done();
|
|
139
140
|
});
|
|
140
141
|
});
|
|
@@ -143,7 +144,7 @@ describe('GlyphManager', () => {
|
|
|
143
144
|
|
|
144
145
|
const manager = createGlyphManager('sans-serif');
|
|
145
146
|
const drawSpy = GlyphManager.TinySDF.prototype.draw = jest.fn().mockImplementation(() => {
|
|
146
|
-
return {data: new Uint8ClampedArray(
|
|
147
|
+
return {data: new Uint8ClampedArray(60 * 60)} as any;
|
|
147
148
|
});
|
|
148
149
|
|
|
149
150
|
// Katakana letter te
|