@loaders.gl/mvt 4.0.0-beta.2 → 4.0.0-beta.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/dist/{dist.min.js → dist.dev.js} +2353 -1734
- package/dist/helpers/binary-util-functions.js.map +1 -0
- package/dist/helpers/mapbox-util-functions.js.map +1 -0
- package/dist/index.cjs +1800 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/{esm/lib → lib}/binary-vector-tile/vector-tile-feature.js +12 -13
- package/dist/lib/binary-vector-tile/vector-tile-feature.js.map +1 -0
- package/dist/{esm/lib → lib}/binary-vector-tile/vector-tile-layer.js +9 -10
- package/dist/lib/binary-vector-tile/vector-tile-layer.js.map +1 -0
- package/dist/{esm/lib/mapbox-vector-tile → lib/binary-vector-tile}/vector-tile.js +2 -3
- package/dist/lib/binary-vector-tile/vector-tile.js.map +1 -0
- package/dist/{esm/lib → lib}/geojson-tiler/clip.js +4 -5
- package/dist/lib/geojson-tiler/clip.js.map +1 -0
- package/dist/{esm/lib → lib}/geojson-tiler/convert.js +2 -2
- package/dist/lib/geojson-tiler/convert.js.map +1 -0
- package/dist/lib/geojson-tiler/feature.js.map +1 -0
- package/dist/{esm/lib → lib}/geojson-tiler/geojson-tiler.js +11 -12
- package/dist/lib/geojson-tiler/geojson-tiler.js.map +1 -0
- package/dist/lib/geojson-tiler/simplify.js.map +1 -0
- package/dist/lib/geojson-tiler/tile.js.map +1 -0
- package/dist/lib/geojson-tiler/transform.js.map +1 -0
- package/dist/{esm/lib → lib}/geojson-tiler/wrap.js +5 -6
- package/dist/lib/geojson-tiler/wrap.js.map +1 -0
- package/dist/{esm/lib → lib}/mapbox-vector-tile/vector-tile-feature.js +12 -13
- package/dist/lib/mapbox-vector-tile/vector-tile-feature.js.map +1 -0
- package/dist/{esm/lib → lib}/mapbox-vector-tile/vector-tile-layer.js +9 -10
- package/dist/lib/mapbox-vector-tile/vector-tile-layer.js.map +1 -0
- package/dist/{esm/lib/binary-vector-tile → lib/mapbox-vector-tile}/vector-tile.js +2 -3
- package/dist/lib/mapbox-vector-tile/vector-tile.js.map +1 -0
- package/dist/{esm/lib → lib}/parse-mvt.js +2 -2
- package/dist/lib/parse-mvt.js.map +1 -0
- package/dist/lib/parse-tilejson.js.map +1 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/{esm/mvt-loader.js → mvt-loader.js} +2 -2
- package/dist/mvt-loader.js.map +1 -0
- package/dist/mvt-source.d.ts +28 -0
- package/dist/mvt-source.d.ts.map +1 -0
- package/dist/mvt-source.js +100 -0
- package/dist/mvt-source.js.map +1 -0
- package/dist/mvt-worker.js +267 -103
- package/dist/{esm/tilejson-loader.js → tilejson-loader.js} +2 -2
- package/dist/tilejson-loader.js.map +1 -0
- package/dist/{esm/workers → workers}/mvt-worker.js +1 -1
- package/dist/workers/mvt-worker.js.map +1 -0
- package/package.json +19 -10
- package/src/index.ts +2 -0
- package/src/mvt-source.ts +110 -0
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.d.ts.map +0 -1
- package/dist/es5/bundle.js +0 -6
- package/dist/es5/bundle.js.map +0 -1
- package/dist/es5/helpers/binary-util-functions.js +0 -82
- package/dist/es5/helpers/binary-util-functions.js.map +0 -1
- package/dist/es5/helpers/mapbox-util-functions.js +0 -50
- package/dist/es5/helpers/mapbox-util-functions.js.map +0 -1
- package/dist/es5/index.js +0 -33
- package/dist/es5/index.js.map +0 -1
- package/dist/es5/lib/binary-vector-tile/vector-tile-feature.js +0 -168
- package/dist/es5/lib/binary-vector-tile/vector-tile-feature.js.map +0 -1
- package/dist/es5/lib/binary-vector-tile/vector-tile-layer.js +0 -62
- package/dist/es5/lib/binary-vector-tile/vector-tile-layer.js.map +0 -1
- package/dist/es5/lib/binary-vector-tile/vector-tile.js +0 -28
- package/dist/es5/lib/binary-vector-tile/vector-tile.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/clip.js +0 -237
- package/dist/es5/lib/geojson-tiler/clip.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/convert.js +0 -161
- package/dist/es5/lib/geojson-tiler/convert.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/feature.js +0 -62
- package/dist/es5/lib/geojson-tiler/feature.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/geojson-tiler.js +0 -186
- package/dist/es5/lib/geojson-tiler/geojson-tiler.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/simplify.js +0 -52
- package/dist/es5/lib/geojson-tiler/simplify.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/tile.js +0 -121
- package/dist/es5/lib/geojson-tiler/tile.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/transform.js +0 -50
- package/dist/es5/lib/geojson-tiler/transform.js.map +0 -1
- package/dist/es5/lib/geojson-tiler/wrap.js +0 -122
- package/dist/es5/lib/geojson-tiler/wrap.js.map +0 -1
- package/dist/es5/lib/mapbox-vector-tile/vector-tile-feature.js +0 -184
- package/dist/es5/lib/mapbox-vector-tile/vector-tile-feature.js.map +0 -1
- package/dist/es5/lib/mapbox-vector-tile/vector-tile-layer.js +0 -62
- package/dist/es5/lib/mapbox-vector-tile/vector-tile-layer.js.map +0 -1
- package/dist/es5/lib/mapbox-vector-tile/vector-tile.js +0 -28
- package/dist/es5/lib/mapbox-vector-tile/vector-tile.js.map +0 -1
- package/dist/es5/lib/parse-mvt.js +0 -144
- package/dist/es5/lib/parse-mvt.js.map +0 -1
- package/dist/es5/lib/parse-tilejson.js +0 -186
- package/dist/es5/lib/parse-tilejson.js.map +0 -1
- package/dist/es5/lib/types.js +0 -2
- package/dist/es5/lib/types.js.map +0 -1
- package/dist/es5/mvt-loader.js +0 -57
- package/dist/es5/mvt-loader.js.map +0 -1
- package/dist/es5/tilejson-loader.js +0 -50
- package/dist/es5/tilejson-loader.js.map +0 -1
- package/dist/es5/workers/mvt-worker.js +0 -6
- package/dist/es5/workers/mvt-worker.js.map +0 -1
- package/dist/esm/bundle.js +0 -4
- package/dist/esm/bundle.js.map +0 -1
- package/dist/esm/helpers/binary-util-functions.js.map +0 -1
- package/dist/esm/helpers/mapbox-util-functions.js.map +0 -1
- package/dist/esm/index.js +0 -4
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/lib/binary-vector-tile/LICENSE.txt +0 -31
- package/dist/esm/lib/binary-vector-tile/vector-tile-feature.js.map +0 -1
- package/dist/esm/lib/binary-vector-tile/vector-tile-layer.js.map +0 -1
- package/dist/esm/lib/binary-vector-tile/vector-tile.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/LICENSE +0 -19
- package/dist/esm/lib/geojson-tiler/clip.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/convert.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/feature.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/geojson-tiler.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/simplify.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/tile.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/transform.js.map +0 -1
- package/dist/esm/lib/geojson-tiler/wrap.js.map +0 -1
- package/dist/esm/lib/mapbox-vector-tile/LICENSE.txt +0 -31
- package/dist/esm/lib/mapbox-vector-tile/vector-tile-feature.js.map +0 -1
- package/dist/esm/lib/mapbox-vector-tile/vector-tile-layer.js.map +0 -1
- package/dist/esm/lib/mapbox-vector-tile/vector-tile.js.map +0 -1
- package/dist/esm/lib/parse-mvt.js.map +0 -1
- package/dist/esm/lib/parse-tilejson.js.map +0 -1
- package/dist/esm/lib/types.js.map +0 -1
- package/dist/esm/mvt-loader.js.map +0 -1
- package/dist/esm/tilejson-loader.js.map +0 -1
- package/dist/esm/workers/mvt-worker.js.map +0 -1
- package/src/bundle.ts +0 -4
- /package/dist/{esm/helpers → helpers}/binary-util-functions.js +0 -0
- /package/dist/{esm/helpers → helpers}/mapbox-util-functions.js +0 -0
- /package/dist/{es5/lib → lib}/binary-vector-tile/LICENSE.txt +0 -0
- /package/dist/{es5/lib → lib}/geojson-tiler/LICENSE +0 -0
- /package/dist/{esm/lib → lib}/geojson-tiler/feature.js +0 -0
- /package/dist/{esm/lib → lib}/geojson-tiler/simplify.js +0 -0
- /package/dist/{esm/lib → lib}/geojson-tiler/tile.js +0 -0
- /package/dist/{esm/lib → lib}/geojson-tiler/transform.js +0 -0
- /package/dist/{es5/lib → lib}/mapbox-vector-tile/LICENSE.txt +0 -0
- /package/dist/{esm/lib → lib}/parse-tilejson.js +0 -0
- /package/dist/{esm/lib → lib}/types.js +0 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1800 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
GeoJSONTiler: () => GeoJSONTiler,
|
|
34
|
+
MVTLoader: () => MVTLoader,
|
|
35
|
+
MVTSource: () => MVTSource,
|
|
36
|
+
MVTWorkerLoader: () => MVTWorkerLoader,
|
|
37
|
+
TileJSONLoader: () => TileJSONLoader
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(src_exports);
|
|
40
|
+
|
|
41
|
+
// src/lib/parse-mvt.ts
|
|
42
|
+
var import_gis = require("@loaders.gl/gis");
|
|
43
|
+
var import_pbf = __toESM(require("pbf"), 1);
|
|
44
|
+
|
|
45
|
+
// src/helpers/mapbox-util-functions.ts
|
|
46
|
+
function classifyRings(rings) {
|
|
47
|
+
const len = rings.length;
|
|
48
|
+
if (len <= 1)
|
|
49
|
+
return [rings];
|
|
50
|
+
const polygons = [];
|
|
51
|
+
let polygon;
|
|
52
|
+
let ccw;
|
|
53
|
+
for (let i2 = 0; i2 < len; i2++) {
|
|
54
|
+
const area = signedArea(rings[i2]);
|
|
55
|
+
if (area === 0)
|
|
56
|
+
continue;
|
|
57
|
+
if (ccw === void 0)
|
|
58
|
+
ccw = area < 0;
|
|
59
|
+
if (ccw === area < 0) {
|
|
60
|
+
if (polygon)
|
|
61
|
+
polygons.push(polygon);
|
|
62
|
+
polygon = [rings[i2]];
|
|
63
|
+
} else if (polygon)
|
|
64
|
+
polygon.push(rings[i2]);
|
|
65
|
+
}
|
|
66
|
+
if (polygon)
|
|
67
|
+
polygons.push(polygon);
|
|
68
|
+
return polygons;
|
|
69
|
+
}
|
|
70
|
+
function signedArea(ring) {
|
|
71
|
+
let sum = 0;
|
|
72
|
+
for (let i2 = 0, j = ring.length - 1, p1, p2; i2 < ring.length; j = i2++) {
|
|
73
|
+
p1 = ring[i2];
|
|
74
|
+
p2 = ring[j];
|
|
75
|
+
sum += (p2[0] - p1[0]) * (p1[1] + p2[1]);
|
|
76
|
+
}
|
|
77
|
+
return sum;
|
|
78
|
+
}
|
|
79
|
+
function readFeature(tag, feature, pbf) {
|
|
80
|
+
if (feature && pbf) {
|
|
81
|
+
if (tag === 1)
|
|
82
|
+
feature.id = pbf.readVarint();
|
|
83
|
+
else if (tag === 2)
|
|
84
|
+
readTag(pbf, feature);
|
|
85
|
+
else if (tag === 3)
|
|
86
|
+
feature.type = pbf.readVarint();
|
|
87
|
+
else if (tag === 4)
|
|
88
|
+
feature._geometry = pbf.pos;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function readTag(pbf, feature) {
|
|
92
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
93
|
+
while (pbf.pos < end) {
|
|
94
|
+
const key = feature._keys[pbf.readVarint()];
|
|
95
|
+
const value = feature._values[pbf.readVarint()];
|
|
96
|
+
feature.properties[key] = value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/lib/mapbox-vector-tile/vector-tile-feature.ts
|
|
101
|
+
var VectorTileFeature = class {
|
|
102
|
+
static get types() {
|
|
103
|
+
return ["Unknown", "Point", "LineString", "Polygon"];
|
|
104
|
+
}
|
|
105
|
+
constructor(pbf, end, extent, keys, values) {
|
|
106
|
+
this.properties = {};
|
|
107
|
+
this.extent = extent;
|
|
108
|
+
this.type = 0;
|
|
109
|
+
this.id = null;
|
|
110
|
+
this._pbf = pbf;
|
|
111
|
+
this._geometry = -1;
|
|
112
|
+
this._keys = keys;
|
|
113
|
+
this._values = values;
|
|
114
|
+
pbf.readFields(readFeature, this, end);
|
|
115
|
+
}
|
|
116
|
+
// eslint-disable-next-line complexity, max-statements
|
|
117
|
+
loadGeometry() {
|
|
118
|
+
const pbf = this._pbf;
|
|
119
|
+
pbf.pos = this._geometry;
|
|
120
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
121
|
+
let cmd2 = 1;
|
|
122
|
+
let length2 = 0;
|
|
123
|
+
let x2 = 0;
|
|
124
|
+
let y2 = 0;
|
|
125
|
+
const lines = [];
|
|
126
|
+
let line;
|
|
127
|
+
while (pbf.pos < end) {
|
|
128
|
+
if (length2 <= 0) {
|
|
129
|
+
const cmdLen2 = pbf.readVarint();
|
|
130
|
+
cmd2 = cmdLen2 & 7;
|
|
131
|
+
length2 = cmdLen2 >> 3;
|
|
132
|
+
}
|
|
133
|
+
length2--;
|
|
134
|
+
if (cmd2 === 1 || cmd2 === 2) {
|
|
135
|
+
x2 += pbf.readSVarint();
|
|
136
|
+
y2 += pbf.readSVarint();
|
|
137
|
+
if (cmd2 === 1) {
|
|
138
|
+
if (line)
|
|
139
|
+
lines.push(line);
|
|
140
|
+
line = [];
|
|
141
|
+
}
|
|
142
|
+
if (line)
|
|
143
|
+
line.push([x2, y2]);
|
|
144
|
+
} else if (cmd2 === 7) {
|
|
145
|
+
if (line) {
|
|
146
|
+
line.push(line[0].slice());
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
throw new Error(`unknown command ${cmd2}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (line)
|
|
153
|
+
lines.push(line);
|
|
154
|
+
return lines;
|
|
155
|
+
}
|
|
156
|
+
// eslint-disable-next-line max-statements
|
|
157
|
+
bbox() {
|
|
158
|
+
const pbf = this._pbf;
|
|
159
|
+
pbf.pos = this._geometry;
|
|
160
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
161
|
+
let cmd2 = 1;
|
|
162
|
+
let length2 = 0;
|
|
163
|
+
let x2 = 0;
|
|
164
|
+
let y2 = 0;
|
|
165
|
+
let x1 = Infinity;
|
|
166
|
+
let x22 = -Infinity;
|
|
167
|
+
let y1 = Infinity;
|
|
168
|
+
let y22 = -Infinity;
|
|
169
|
+
while (pbf.pos < end) {
|
|
170
|
+
if (length2 <= 0) {
|
|
171
|
+
const cmdLen2 = pbf.readVarint();
|
|
172
|
+
cmd2 = cmdLen2 & 7;
|
|
173
|
+
length2 = cmdLen2 >> 3;
|
|
174
|
+
}
|
|
175
|
+
length2--;
|
|
176
|
+
if (cmd2 === 1 || cmd2 === 2) {
|
|
177
|
+
x2 += pbf.readSVarint();
|
|
178
|
+
y2 += pbf.readSVarint();
|
|
179
|
+
if (x2 < x1)
|
|
180
|
+
x1 = x2;
|
|
181
|
+
if (x2 > x22)
|
|
182
|
+
x22 = x2;
|
|
183
|
+
if (y2 < y1)
|
|
184
|
+
y1 = y2;
|
|
185
|
+
if (y2 > y22)
|
|
186
|
+
y22 = y2;
|
|
187
|
+
} else if (cmd2 !== 7) {
|
|
188
|
+
throw new Error(`unknown command ${cmd2}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return [x1, y1, x22, y22];
|
|
192
|
+
}
|
|
193
|
+
_toGeoJSON(transform) {
|
|
194
|
+
let coords = this.loadGeometry();
|
|
195
|
+
let type = VectorTileFeature.types[this.type];
|
|
196
|
+
let i2;
|
|
197
|
+
let j;
|
|
198
|
+
switch (this.type) {
|
|
199
|
+
case 1:
|
|
200
|
+
const points = [];
|
|
201
|
+
for (i2 = 0; i2 < coords.length; i2++) {
|
|
202
|
+
points[i2] = coords[i2][0];
|
|
203
|
+
}
|
|
204
|
+
coords = points;
|
|
205
|
+
transform(coords, this);
|
|
206
|
+
break;
|
|
207
|
+
case 2:
|
|
208
|
+
for (i2 = 0; i2 < coords.length; i2++) {
|
|
209
|
+
transform(coords[i2], this);
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
case 3:
|
|
213
|
+
coords = classifyRings(coords);
|
|
214
|
+
for (i2 = 0; i2 < coords.length; i2++) {
|
|
215
|
+
for (j = 0; j < coords[i2].length; j++) {
|
|
216
|
+
transform(coords[i2][j], this);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
if (coords.length === 1) {
|
|
222
|
+
coords = coords[0];
|
|
223
|
+
} else {
|
|
224
|
+
type = `Multi${type}`;
|
|
225
|
+
}
|
|
226
|
+
const result = {
|
|
227
|
+
type: "Feature",
|
|
228
|
+
geometry: {
|
|
229
|
+
type,
|
|
230
|
+
coordinates: coords
|
|
231
|
+
},
|
|
232
|
+
properties: this.properties
|
|
233
|
+
};
|
|
234
|
+
if (this.id !== null) {
|
|
235
|
+
result.id = this.id;
|
|
236
|
+
}
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
toGeoJSON(options) {
|
|
240
|
+
if (typeof options === "function") {
|
|
241
|
+
return this._toGeoJSON(options);
|
|
242
|
+
}
|
|
243
|
+
const { x: x2, y: y2, z } = options;
|
|
244
|
+
const size = this.extent * Math.pow(2, z);
|
|
245
|
+
const x0 = this.extent * x2;
|
|
246
|
+
const y0 = this.extent * y2;
|
|
247
|
+
function project2(line) {
|
|
248
|
+
for (let j = 0; j < line.length; j++) {
|
|
249
|
+
const p = line[j];
|
|
250
|
+
p[0] = (p[0] + x0) * 360 / size - 180;
|
|
251
|
+
const y22 = 180 - (p[1] + y0) * 360 / size;
|
|
252
|
+
p[1] = 360 / Math.PI * Math.atan(Math.exp(y22 * Math.PI / 180)) - 90;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return this._toGeoJSON(project2);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// src/lib/mapbox-vector-tile/vector-tile-layer.ts
|
|
260
|
+
var VectorTileLayer = class {
|
|
261
|
+
constructor(pbf, end) {
|
|
262
|
+
this.version = 1;
|
|
263
|
+
this.name = "";
|
|
264
|
+
this.extent = 4096;
|
|
265
|
+
this.length = 0;
|
|
266
|
+
this._pbf = pbf;
|
|
267
|
+
this._keys = [];
|
|
268
|
+
this._values = [];
|
|
269
|
+
this._features = [];
|
|
270
|
+
pbf.readFields(readLayer, this, end);
|
|
271
|
+
this.length = this._features.length;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* return feature `i` from this layer as a `VectorTileFeature`
|
|
275
|
+
* @param index
|
|
276
|
+
* @returns feature
|
|
277
|
+
*/
|
|
278
|
+
feature(i2) {
|
|
279
|
+
if (i2 < 0 || i2 >= this._features.length) {
|
|
280
|
+
throw new Error("feature index out of bounds");
|
|
281
|
+
}
|
|
282
|
+
this._pbf.pos = this._features[i2];
|
|
283
|
+
const end = this._pbf.readVarint() + this._pbf.pos;
|
|
284
|
+
return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
function readLayer(tag, layer, pbf) {
|
|
288
|
+
if (layer && pbf) {
|
|
289
|
+
if (tag === 15)
|
|
290
|
+
layer.version = pbf.readVarint();
|
|
291
|
+
else if (tag === 1)
|
|
292
|
+
layer.name = pbf.readString();
|
|
293
|
+
else if (tag === 5)
|
|
294
|
+
layer.extent = pbf.readVarint();
|
|
295
|
+
else if (tag === 2)
|
|
296
|
+
layer._features.push(pbf.pos);
|
|
297
|
+
else if (tag === 3)
|
|
298
|
+
layer._keys.push(pbf.readString());
|
|
299
|
+
else if (tag === 4)
|
|
300
|
+
layer._values.push(readValueMessage(pbf));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function readValueMessage(pbf) {
|
|
304
|
+
let value = null;
|
|
305
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
306
|
+
while (pbf.pos < end) {
|
|
307
|
+
const tag = pbf.readVarint() >> 3;
|
|
308
|
+
value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null;
|
|
309
|
+
}
|
|
310
|
+
return value;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// src/lib/mapbox-vector-tile/vector-tile.ts
|
|
314
|
+
var VectorTile = class {
|
|
315
|
+
constructor(pbf, end) {
|
|
316
|
+
this.layers = pbf.readFields(readTile, {}, end);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
function readTile(tag, layers, pbf) {
|
|
320
|
+
if (tag === 3) {
|
|
321
|
+
if (pbf) {
|
|
322
|
+
const layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos);
|
|
323
|
+
if (layer.length && layers) {
|
|
324
|
+
layers[layer.name] = layer;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// src/helpers/binary-util-functions.ts
|
|
331
|
+
var import_polygon = require("@math.gl/polygon");
|
|
332
|
+
function classifyRings2(geom) {
|
|
333
|
+
const len = geom.indices.length;
|
|
334
|
+
const type = "Polygon";
|
|
335
|
+
if (len <= 1) {
|
|
336
|
+
return {
|
|
337
|
+
type,
|
|
338
|
+
data: geom.data,
|
|
339
|
+
areas: [[(0, import_polygon.getPolygonSignedArea)(geom.data)]],
|
|
340
|
+
indices: [geom.indices]
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
const areas = [];
|
|
344
|
+
const polygons = [];
|
|
345
|
+
let ringAreas = [];
|
|
346
|
+
let polygon = [];
|
|
347
|
+
let ccw;
|
|
348
|
+
let offset = 0;
|
|
349
|
+
for (let endIndex, i2 = 0, startIndex; i2 < len; i2++) {
|
|
350
|
+
startIndex = geom.indices[i2] - offset;
|
|
351
|
+
endIndex = geom.indices[i2 + 1] - offset || geom.data.length;
|
|
352
|
+
const shape = geom.data.slice(startIndex, endIndex);
|
|
353
|
+
const area = (0, import_polygon.getPolygonSignedArea)(shape);
|
|
354
|
+
if (area === 0) {
|
|
355
|
+
const before = geom.data.slice(0, startIndex);
|
|
356
|
+
const after = geom.data.slice(endIndex);
|
|
357
|
+
geom.data = before.concat(after);
|
|
358
|
+
offset += endIndex - startIndex;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (ccw === void 0)
|
|
362
|
+
ccw = area < 0;
|
|
363
|
+
if (ccw === area < 0) {
|
|
364
|
+
if (polygon.length) {
|
|
365
|
+
areas.push(ringAreas);
|
|
366
|
+
polygons.push(polygon);
|
|
367
|
+
}
|
|
368
|
+
polygon = [startIndex];
|
|
369
|
+
ringAreas = [area];
|
|
370
|
+
} else {
|
|
371
|
+
ringAreas.push(area);
|
|
372
|
+
polygon.push(startIndex);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (ringAreas)
|
|
376
|
+
areas.push(ringAreas);
|
|
377
|
+
if (polygon.length)
|
|
378
|
+
polygons.push(polygon);
|
|
379
|
+
return { type, areas, indices: polygons, data: geom.data };
|
|
380
|
+
}
|
|
381
|
+
function project(data, x0, y0, size) {
|
|
382
|
+
for (let j = 0, jl = data.length; j < jl; j += 2) {
|
|
383
|
+
data[j] = (data[j] + x0) * 360 / size - 180;
|
|
384
|
+
const y2 = 180 - (data[j + 1] + y0) * 360 / size;
|
|
385
|
+
data[j + 1] = 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function readFeature2(tag, feature, pbf) {
|
|
389
|
+
if (feature && pbf) {
|
|
390
|
+
if (tag === 1)
|
|
391
|
+
feature.id = pbf.readVarint();
|
|
392
|
+
else if (tag === 2)
|
|
393
|
+
readTag2(pbf, feature);
|
|
394
|
+
else if (tag === 3)
|
|
395
|
+
feature.type = pbf.readVarint();
|
|
396
|
+
else if (tag === 4)
|
|
397
|
+
feature._geometry = pbf.pos;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function readTag2(pbf, feature) {
|
|
401
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
402
|
+
while (pbf.pos < end) {
|
|
403
|
+
const key = feature._keys[pbf.readVarint()];
|
|
404
|
+
const value = feature._values[pbf.readVarint()];
|
|
405
|
+
feature.properties[key] = value;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/lib/binary-vector-tile/vector-tile-feature.ts
|
|
410
|
+
var endPos;
|
|
411
|
+
var cmd;
|
|
412
|
+
var cmdLen;
|
|
413
|
+
var length;
|
|
414
|
+
var x;
|
|
415
|
+
var y;
|
|
416
|
+
var i;
|
|
417
|
+
var VectorTileFeature2 = class {
|
|
418
|
+
// eslint-disable-next-line max-params
|
|
419
|
+
constructor(pbf, end, extent, keys, values, geometryInfo) {
|
|
420
|
+
this.properties = {};
|
|
421
|
+
this.extent = extent;
|
|
422
|
+
this.type = 0;
|
|
423
|
+
this.id = null;
|
|
424
|
+
this._pbf = pbf;
|
|
425
|
+
this._geometry = -1;
|
|
426
|
+
this._keys = keys;
|
|
427
|
+
this._values = values;
|
|
428
|
+
this._geometryInfo = geometryInfo;
|
|
429
|
+
pbf.readFields(readFeature2, this, end);
|
|
430
|
+
}
|
|
431
|
+
// eslint-disable-next-line complexity, max-statements
|
|
432
|
+
loadGeometry() {
|
|
433
|
+
const pbf = this._pbf;
|
|
434
|
+
pbf.pos = this._geometry;
|
|
435
|
+
endPos = pbf.readVarint() + pbf.pos;
|
|
436
|
+
cmd = 1;
|
|
437
|
+
length = 0;
|
|
438
|
+
x = 0;
|
|
439
|
+
y = 0;
|
|
440
|
+
i = 0;
|
|
441
|
+
const indices = [];
|
|
442
|
+
const data = [];
|
|
443
|
+
while (pbf.pos < endPos) {
|
|
444
|
+
if (length <= 0) {
|
|
445
|
+
cmdLen = pbf.readVarint();
|
|
446
|
+
cmd = cmdLen & 7;
|
|
447
|
+
length = cmdLen >> 3;
|
|
448
|
+
}
|
|
449
|
+
length--;
|
|
450
|
+
if (cmd === 1 || cmd === 2) {
|
|
451
|
+
x += pbf.readSVarint();
|
|
452
|
+
y += pbf.readSVarint();
|
|
453
|
+
if (cmd === 1) {
|
|
454
|
+
indices.push(i);
|
|
455
|
+
}
|
|
456
|
+
data.push(x, y);
|
|
457
|
+
i += 2;
|
|
458
|
+
} else if (cmd === 7) {
|
|
459
|
+
if (i > 0) {
|
|
460
|
+
const start = indices[indices.length - 1];
|
|
461
|
+
data.push(data[start], data[start + 1]);
|
|
462
|
+
i += 2;
|
|
463
|
+
}
|
|
464
|
+
} else {
|
|
465
|
+
throw new Error(`unknown command ${cmd}`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return { data, indices };
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
*
|
|
472
|
+
* @param transform
|
|
473
|
+
* @returns result
|
|
474
|
+
*/
|
|
475
|
+
_toBinaryCoordinates(transform) {
|
|
476
|
+
const geom = this.loadGeometry();
|
|
477
|
+
let geometry;
|
|
478
|
+
transform(geom.data, this);
|
|
479
|
+
const coordLength = 2;
|
|
480
|
+
switch (this.type) {
|
|
481
|
+
case 1:
|
|
482
|
+
this._geometryInfo.pointFeaturesCount++;
|
|
483
|
+
this._geometryInfo.pointPositionsCount += geom.indices.length;
|
|
484
|
+
geometry = { type: "Point", ...geom };
|
|
485
|
+
break;
|
|
486
|
+
case 2:
|
|
487
|
+
this._geometryInfo.lineFeaturesCount++;
|
|
488
|
+
this._geometryInfo.linePathsCount += geom.indices.length;
|
|
489
|
+
this._geometryInfo.linePositionsCount += geom.data.length / coordLength;
|
|
490
|
+
geometry = { type: "LineString", ...geom };
|
|
491
|
+
break;
|
|
492
|
+
case 3:
|
|
493
|
+
geometry = classifyRings2(geom);
|
|
494
|
+
this._geometryInfo.polygonFeaturesCount++;
|
|
495
|
+
this._geometryInfo.polygonObjectsCount += geometry.indices.length;
|
|
496
|
+
for (const indices of geometry.indices) {
|
|
497
|
+
this._geometryInfo.polygonRingsCount += indices.length;
|
|
498
|
+
}
|
|
499
|
+
this._geometryInfo.polygonPositionsCount += geometry.data.length / coordLength;
|
|
500
|
+
break;
|
|
501
|
+
default:
|
|
502
|
+
throw new Error(`Invalid geometry type: ${this.type}`);
|
|
503
|
+
}
|
|
504
|
+
const result = { type: "Feature", geometry, properties: this.properties };
|
|
505
|
+
if (this.id !== null) {
|
|
506
|
+
result.id = this.id;
|
|
507
|
+
}
|
|
508
|
+
return result;
|
|
509
|
+
}
|
|
510
|
+
toBinaryCoordinates(options) {
|
|
511
|
+
if (typeof options === "function") {
|
|
512
|
+
return this._toBinaryCoordinates(options);
|
|
513
|
+
}
|
|
514
|
+
const { x: x2, y: y2, z } = options;
|
|
515
|
+
const size = this.extent * Math.pow(2, z);
|
|
516
|
+
const x0 = this.extent * x2;
|
|
517
|
+
const y0 = this.extent * y2;
|
|
518
|
+
return this._toBinaryCoordinates((data) => project(data, x0, y0, size));
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
// src/lib/binary-vector-tile/vector-tile-layer.ts
|
|
523
|
+
var VectorTileLayer2 = class {
|
|
524
|
+
constructor(pbf, end) {
|
|
525
|
+
this.version = 1;
|
|
526
|
+
this.name = "";
|
|
527
|
+
this.extent = 4096;
|
|
528
|
+
this.length = 0;
|
|
529
|
+
this._pbf = pbf;
|
|
530
|
+
this._keys = [];
|
|
531
|
+
this._values = [];
|
|
532
|
+
this._features = [];
|
|
533
|
+
pbf.readFields(readLayer2, this, end);
|
|
534
|
+
this.length = this._features.length;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* return feature `i` from this layer as a `VectorTileFeature`
|
|
538
|
+
*
|
|
539
|
+
* @param index
|
|
540
|
+
* @param geometryInfo
|
|
541
|
+
* @returns {VectorTileFeature}
|
|
542
|
+
*/
|
|
543
|
+
feature(i2, geometryInfo) {
|
|
544
|
+
if (i2 < 0 || i2 >= this._features.length) {
|
|
545
|
+
throw new Error("feature index out of bounds");
|
|
546
|
+
}
|
|
547
|
+
this._pbf.pos = this._features[i2];
|
|
548
|
+
const end = this._pbf.readVarint() + this._pbf.pos;
|
|
549
|
+
return new VectorTileFeature2(
|
|
550
|
+
this._pbf,
|
|
551
|
+
end,
|
|
552
|
+
this.extent,
|
|
553
|
+
this._keys,
|
|
554
|
+
this._values,
|
|
555
|
+
geometryInfo
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
function readLayer2(tag, layer, pbf) {
|
|
560
|
+
if (layer && pbf) {
|
|
561
|
+
if (tag === 15)
|
|
562
|
+
layer.version = pbf.readVarint();
|
|
563
|
+
else if (tag === 1)
|
|
564
|
+
layer.name = pbf.readString();
|
|
565
|
+
else if (tag === 5)
|
|
566
|
+
layer.extent = pbf.readVarint();
|
|
567
|
+
else if (tag === 2)
|
|
568
|
+
layer._features.push(pbf.pos);
|
|
569
|
+
else if (tag === 3)
|
|
570
|
+
layer._keys.push(pbf.readString());
|
|
571
|
+
else if (tag === 4)
|
|
572
|
+
layer._values.push(readValueMessage2(pbf));
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function readValueMessage2(pbf) {
|
|
576
|
+
let value = null;
|
|
577
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
578
|
+
while (pbf.pos < end) {
|
|
579
|
+
const tag = pbf.readVarint() >> 3;
|
|
580
|
+
value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null;
|
|
581
|
+
}
|
|
582
|
+
return value;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/lib/binary-vector-tile/vector-tile.ts
|
|
586
|
+
var VectorTile2 = class {
|
|
587
|
+
constructor(pbf, end) {
|
|
588
|
+
this.layers = pbf.readFields(readTile2, {}, end);
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
function readTile2(tag, layers, pbf) {
|
|
592
|
+
if (tag === 3) {
|
|
593
|
+
if (pbf) {
|
|
594
|
+
const layer = new VectorTileLayer2(pbf, pbf.readVarint() + pbf.pos);
|
|
595
|
+
if (layer.length && layers) {
|
|
596
|
+
layers[layer.name] = layer;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// src/lib/parse-mvt.ts
|
|
603
|
+
function parseMVT(arrayBuffer, options) {
|
|
604
|
+
var _a, _b;
|
|
605
|
+
const mvtOptions = normalizeOptions(options);
|
|
606
|
+
const shape = ((_a = options == null ? void 0 : options.gis) == null ? void 0 : _a.format) || ((_b = options == null ? void 0 : options.mvt) == null ? void 0 : _b.shape) || (options == null ? void 0 : options.shape);
|
|
607
|
+
switch (shape) {
|
|
608
|
+
case "columnar-table":
|
|
609
|
+
return { shape: "columnar-table", data: parseToBinary(arrayBuffer, mvtOptions) };
|
|
610
|
+
case "geojson-table": {
|
|
611
|
+
const table = {
|
|
612
|
+
shape: "geojson-table",
|
|
613
|
+
type: "FeatureCollection",
|
|
614
|
+
features: parseToGeojsonFeatures(arrayBuffer, mvtOptions)
|
|
615
|
+
};
|
|
616
|
+
return table;
|
|
617
|
+
}
|
|
618
|
+
case "geojson":
|
|
619
|
+
return parseToGeojsonFeatures(arrayBuffer, mvtOptions);
|
|
620
|
+
case "binary-geometry":
|
|
621
|
+
return parseToBinary(arrayBuffer, mvtOptions);
|
|
622
|
+
case "binary":
|
|
623
|
+
return parseToBinary(arrayBuffer, mvtOptions);
|
|
624
|
+
default:
|
|
625
|
+
throw new Error(shape || "undefined shape");
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
function parseToBinary(arrayBuffer, options) {
|
|
629
|
+
const [flatGeoJsonFeatures, geometryInfo] = parseToFlatGeoJson(arrayBuffer, options);
|
|
630
|
+
const binaryData = (0, import_gis.flatGeojsonToBinary)(flatGeoJsonFeatures, geometryInfo);
|
|
631
|
+
binaryData.byteLength = arrayBuffer.byteLength;
|
|
632
|
+
return binaryData;
|
|
633
|
+
}
|
|
634
|
+
function parseToFlatGeoJson(arrayBuffer, options) {
|
|
635
|
+
const features = [];
|
|
636
|
+
const geometryInfo = {
|
|
637
|
+
coordLength: 2,
|
|
638
|
+
pointPositionsCount: 0,
|
|
639
|
+
pointFeaturesCount: 0,
|
|
640
|
+
linePositionsCount: 0,
|
|
641
|
+
linePathsCount: 0,
|
|
642
|
+
lineFeaturesCount: 0,
|
|
643
|
+
polygonPositionsCount: 0,
|
|
644
|
+
polygonObjectsCount: 0,
|
|
645
|
+
polygonRingsCount: 0,
|
|
646
|
+
polygonFeaturesCount: 0
|
|
647
|
+
};
|
|
648
|
+
if (arrayBuffer.byteLength <= 0) {
|
|
649
|
+
return [features, geometryInfo];
|
|
650
|
+
}
|
|
651
|
+
const tile = new VectorTile2(new import_pbf.default(arrayBuffer));
|
|
652
|
+
const selectedLayers = options && Array.isArray(options.layers) ? options.layers : Object.keys(tile.layers);
|
|
653
|
+
selectedLayers.forEach((layerName) => {
|
|
654
|
+
const vectorTileLayer = tile.layers[layerName];
|
|
655
|
+
if (!vectorTileLayer) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
for (let i2 = 0; i2 < vectorTileLayer.length; i2++) {
|
|
659
|
+
const vectorTileFeature = vectorTileLayer.feature(i2, geometryInfo);
|
|
660
|
+
const decodedFeature = getDecodedFeatureBinary(vectorTileFeature, options, layerName);
|
|
661
|
+
features.push(decodedFeature);
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
return [features, geometryInfo];
|
|
665
|
+
}
|
|
666
|
+
function parseToGeojsonFeatures(arrayBuffer, options) {
|
|
667
|
+
if (arrayBuffer.byteLength <= 0) {
|
|
668
|
+
return [];
|
|
669
|
+
}
|
|
670
|
+
const features = [];
|
|
671
|
+
const tile = new VectorTile(new import_pbf.default(arrayBuffer));
|
|
672
|
+
const selectedLayers = Array.isArray(options.layers) ? options.layers : Object.keys(tile.layers);
|
|
673
|
+
selectedLayers.forEach((layerName) => {
|
|
674
|
+
const vectorTileLayer = tile.layers[layerName];
|
|
675
|
+
if (!vectorTileLayer) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
for (let i2 = 0; i2 < vectorTileLayer.length; i2++) {
|
|
679
|
+
const vectorTileFeature = vectorTileLayer.feature(i2);
|
|
680
|
+
const decodedFeature = getDecodedFeature(vectorTileFeature, options, layerName);
|
|
681
|
+
features.push(decodedFeature);
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
return features;
|
|
685
|
+
}
|
|
686
|
+
function normalizeOptions(options) {
|
|
687
|
+
var _a;
|
|
688
|
+
if (!(options == null ? void 0 : options.mvt)) {
|
|
689
|
+
throw new Error("mvt options required");
|
|
690
|
+
}
|
|
691
|
+
const wgs84Coordinates = ((_a = options.mvt) == null ? void 0 : _a.coordinates) === "wgs84";
|
|
692
|
+
const { tileIndex } = options.mvt;
|
|
693
|
+
const hasTileIndex = tileIndex && Number.isFinite(tileIndex.x) && Number.isFinite(tileIndex.y) && Number.isFinite(tileIndex.z);
|
|
694
|
+
if (wgs84Coordinates && !hasTileIndex) {
|
|
695
|
+
throw new Error("MVT Loader: WGS84 coordinates need tileIndex property");
|
|
696
|
+
}
|
|
697
|
+
return options.mvt;
|
|
698
|
+
}
|
|
699
|
+
function getDecodedFeature(feature, options, layerName) {
|
|
700
|
+
const decodedFeature = feature.toGeoJSON(
|
|
701
|
+
// @ts-expect-error What is going on here?
|
|
702
|
+
options.coordinates === "wgs84" ? options.tileIndex : transformToLocalCoordinates
|
|
703
|
+
);
|
|
704
|
+
if (options.layerProperty) {
|
|
705
|
+
decodedFeature.properties[options.layerProperty] = layerName;
|
|
706
|
+
}
|
|
707
|
+
return decodedFeature;
|
|
708
|
+
}
|
|
709
|
+
function getDecodedFeatureBinary(feature, options, layerName) {
|
|
710
|
+
const decodedFeature = feature.toBinaryCoordinates(
|
|
711
|
+
// @ts-expect-error What is going on here?
|
|
712
|
+
options.coordinates === "wgs84" ? options.tileIndex : transformToLocalCoordinatesBinary
|
|
713
|
+
);
|
|
714
|
+
if (options.layerProperty && decodedFeature.properties) {
|
|
715
|
+
decodedFeature.properties[options.layerProperty] = layerName;
|
|
716
|
+
}
|
|
717
|
+
return decodedFeature;
|
|
718
|
+
}
|
|
719
|
+
function transformToLocalCoordinates(line, feature) {
|
|
720
|
+
const { extent } = feature;
|
|
721
|
+
for (let i2 = 0; i2 < line.length; i2++) {
|
|
722
|
+
const p = line[i2];
|
|
723
|
+
p[0] /= extent;
|
|
724
|
+
p[1] /= extent;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
function transformToLocalCoordinatesBinary(data, feature) {
|
|
728
|
+
const { extent } = feature;
|
|
729
|
+
for (let i2 = 0, il = data.length; i2 < il; ++i2) {
|
|
730
|
+
data[i2] /= extent;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// src/mvt-loader.ts
|
|
735
|
+
var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
|
|
736
|
+
var MVTWorkerLoader = {
|
|
737
|
+
name: "Mapbox Vector Tile",
|
|
738
|
+
id: "mvt",
|
|
739
|
+
module: "mvt",
|
|
740
|
+
version: VERSION,
|
|
741
|
+
// Note: ArcGIS uses '.pbf' extension and 'application/octet-stream'
|
|
742
|
+
extensions: ["mvt", "pbf"],
|
|
743
|
+
mimeTypes: [
|
|
744
|
+
// https://www.iana.org/assignments/media-types/application/vnd.mapbox-vector-tile
|
|
745
|
+
"application/vnd.mapbox-vector-tile",
|
|
746
|
+
"application/x-protobuf"
|
|
747
|
+
// 'application/octet-stream'
|
|
748
|
+
],
|
|
749
|
+
worker: true,
|
|
750
|
+
category: "geometry",
|
|
751
|
+
options: {
|
|
752
|
+
mvt: {
|
|
753
|
+
shape: "geojson",
|
|
754
|
+
coordinates: "local",
|
|
755
|
+
layerProperty: "layerName",
|
|
756
|
+
layers: void 0,
|
|
757
|
+
tileIndex: null
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
var MVTLoader = {
|
|
762
|
+
...MVTWorkerLoader,
|
|
763
|
+
parse: async (arrayBuffer, options) => parseMVT(arrayBuffer, options),
|
|
764
|
+
parseSync: parseMVT,
|
|
765
|
+
binary: true
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
// src/lib/parse-tilejson.ts
|
|
769
|
+
var isObject = (x2) => x2 !== null && typeof x2 === "object";
|
|
770
|
+
function parseTileJSON(jsonMetadata) {
|
|
771
|
+
var _a;
|
|
772
|
+
if (!jsonMetadata || !isObject(jsonMetadata)) {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
const boundingBox = parseBounds(jsonMetadata.bounds);
|
|
776
|
+
const center = parseCenter(jsonMetadata.center);
|
|
777
|
+
const maxZoom = safeParseFloat(jsonMetadata.maxzoom);
|
|
778
|
+
const minZoom = safeParseFloat(jsonMetadata.minzoom);
|
|
779
|
+
let tileJSON = {
|
|
780
|
+
name: jsonMetadata.name || "",
|
|
781
|
+
description: jsonMetadata.description || "",
|
|
782
|
+
boundingBox,
|
|
783
|
+
center,
|
|
784
|
+
maxZoom,
|
|
785
|
+
minZoom,
|
|
786
|
+
layers: []
|
|
787
|
+
};
|
|
788
|
+
if (typeof (jsonMetadata == null ? void 0 : jsonMetadata.json) === "string") {
|
|
789
|
+
try {
|
|
790
|
+
tileJSON.metaJson = JSON.parse(jsonMetadata.json);
|
|
791
|
+
} catch (err) {
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
let layers = parseTilestatsLayers((_a = tileJSON.metaJson) == null ? void 0 : _a.tilestats);
|
|
795
|
+
if (layers.length === 0) {
|
|
796
|
+
layers = parseTileJSONLayers(jsonMetadata.vector_layers);
|
|
797
|
+
}
|
|
798
|
+
tileJSON = {
|
|
799
|
+
...tileJSON,
|
|
800
|
+
layers
|
|
801
|
+
};
|
|
802
|
+
return tileJSON;
|
|
803
|
+
}
|
|
804
|
+
function parseTileJSONLayers(layers) {
|
|
805
|
+
if (!Array.isArray(layers)) {
|
|
806
|
+
return [];
|
|
807
|
+
}
|
|
808
|
+
return layers.map((layer) => ({
|
|
809
|
+
name: layer.id || "",
|
|
810
|
+
fields: Object.entries(layer.fields || []).map(([key, datatype]) => ({
|
|
811
|
+
name: key,
|
|
812
|
+
...attributeTypeToFieldType(String(datatype))
|
|
813
|
+
}))
|
|
814
|
+
}));
|
|
815
|
+
}
|
|
816
|
+
function parseTilestatsLayers(tilestats) {
|
|
817
|
+
if (isObject(tilestats) && Array.isArray(tilestats.layers)) {
|
|
818
|
+
return tilestats.layers.map((layer) => parseTilestatsForLayer(layer));
|
|
819
|
+
}
|
|
820
|
+
return [];
|
|
821
|
+
}
|
|
822
|
+
function parseTilestatsForLayer(layer) {
|
|
823
|
+
const fields = [];
|
|
824
|
+
const indexedAttributes = {};
|
|
825
|
+
const attributes = layer.attributes || [];
|
|
826
|
+
for (const attr of attributes) {
|
|
827
|
+
const name = attr.attribute;
|
|
828
|
+
if (typeof name === "string") {
|
|
829
|
+
if (name.split("|").length > 1) {
|
|
830
|
+
const fname = name.split("|")[0];
|
|
831
|
+
indexedAttributes[fname] = indexedAttributes[fname] || [];
|
|
832
|
+
indexedAttributes[fname].push(attr);
|
|
833
|
+
} else if (!fields[name]) {
|
|
834
|
+
fields[name] = attributeToField(attr);
|
|
835
|
+
} else {
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return {
|
|
840
|
+
name: layer.layer || "",
|
|
841
|
+
dominantGeometry: layer.geometry,
|
|
842
|
+
fields
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
function parseBounds(bounds) {
|
|
846
|
+
const result = fromArrayOrString(bounds);
|
|
847
|
+
if (Array.isArray(result) && result.length === 4 && [result[0], result[2]].every(isLng) && [result[1], result[3]].every(isLat)) {
|
|
848
|
+
return [
|
|
849
|
+
[result[0], result[1]],
|
|
850
|
+
[result[2], result[3]]
|
|
851
|
+
];
|
|
852
|
+
}
|
|
853
|
+
return void 0;
|
|
854
|
+
}
|
|
855
|
+
function parseCenter(center) {
|
|
856
|
+
const result = fromArrayOrString(center);
|
|
857
|
+
if (Array.isArray(result) && result.length === 3 && isLng(result[0]) && isLat(result[1]) && isZoom(result[2])) {
|
|
858
|
+
return result;
|
|
859
|
+
}
|
|
860
|
+
return null;
|
|
861
|
+
}
|
|
862
|
+
function safeParseFloat(input) {
|
|
863
|
+
const result = typeof input === "string" ? parseFloat(input) : typeof input === "number" ? input : null;
|
|
864
|
+
return result === null || isNaN(result) ? null : result;
|
|
865
|
+
}
|
|
866
|
+
function isLat(num) {
|
|
867
|
+
return Number.isFinite(num) && num <= 90 && num >= -90;
|
|
868
|
+
}
|
|
869
|
+
function isLng(num) {
|
|
870
|
+
return Number.isFinite(num) && num <= 180 && num >= -180;
|
|
871
|
+
}
|
|
872
|
+
function isZoom(num) {
|
|
873
|
+
return Number.isFinite(num) && num >= 0 && num <= 22;
|
|
874
|
+
}
|
|
875
|
+
function fromArrayOrString(data) {
|
|
876
|
+
if (typeof data === "string") {
|
|
877
|
+
return data.split(",").map(parseFloat);
|
|
878
|
+
} else if (Array.isArray(data)) {
|
|
879
|
+
return data;
|
|
880
|
+
}
|
|
881
|
+
return null;
|
|
882
|
+
}
|
|
883
|
+
var attrTypeMap = {
|
|
884
|
+
number: {
|
|
885
|
+
type: "float32"
|
|
886
|
+
},
|
|
887
|
+
numeric: {
|
|
888
|
+
type: "float32"
|
|
889
|
+
},
|
|
890
|
+
string: {
|
|
891
|
+
type: "utf8"
|
|
892
|
+
},
|
|
893
|
+
vachar: {
|
|
894
|
+
type: "utf8"
|
|
895
|
+
},
|
|
896
|
+
float: {
|
|
897
|
+
type: "float32"
|
|
898
|
+
},
|
|
899
|
+
int: {
|
|
900
|
+
type: "int32"
|
|
901
|
+
},
|
|
902
|
+
int4: {
|
|
903
|
+
type: "int32"
|
|
904
|
+
},
|
|
905
|
+
boolean: {
|
|
906
|
+
type: "boolean"
|
|
907
|
+
},
|
|
908
|
+
bool: {
|
|
909
|
+
type: "boolean"
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
function attributeToField(attribute = {}) {
|
|
913
|
+
const fieldTypes = attributeTypeToFieldType(attribute.type);
|
|
914
|
+
return {
|
|
915
|
+
name: attribute.attribute,
|
|
916
|
+
// what happens if attribute type is string...
|
|
917
|
+
// filterProps: getFilterProps(fieldTypes.type, attribute),
|
|
918
|
+
...fieldTypes
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
function attributeTypeToFieldType(aType) {
|
|
922
|
+
const type = aType.toLowerCase();
|
|
923
|
+
if (!type || !attrTypeMap[type]) {
|
|
924
|
+
}
|
|
925
|
+
return attrTypeMap[type] || { type: "string" };
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
// src/tilejson-loader.ts
|
|
929
|
+
var VERSION2 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
|
|
930
|
+
var TileJSONLoader = {
|
|
931
|
+
name: "TileJSON",
|
|
932
|
+
id: "tilejson",
|
|
933
|
+
module: "pmtiles",
|
|
934
|
+
version: VERSION2,
|
|
935
|
+
worker: true,
|
|
936
|
+
extensions: ["json"],
|
|
937
|
+
mimeTypes: ["application/json"],
|
|
938
|
+
text: true,
|
|
939
|
+
options: {
|
|
940
|
+
tilejson: {}
|
|
941
|
+
},
|
|
942
|
+
parse: async (arrayBuffer, options) => {
|
|
943
|
+
const jsonString = new TextDecoder().decode(arrayBuffer);
|
|
944
|
+
const json = JSON.parse(jsonString);
|
|
945
|
+
return parseTileJSON(json);
|
|
946
|
+
},
|
|
947
|
+
parseTextSync: (text, options) => {
|
|
948
|
+
const json = JSON.parse(text);
|
|
949
|
+
return parseTileJSON(json);
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
// src/mvt-source.ts
|
|
954
|
+
var import_loader_utils = require("@loaders.gl/loader-utils");
|
|
955
|
+
var import_images = require("@loaders.gl/images");
|
|
956
|
+
var import_mvt = require("@loaders.gl/mvt");
|
|
957
|
+
var MVTSource = class extends import_loader_utils.DataSource {
|
|
958
|
+
constructor(props) {
|
|
959
|
+
super(props);
|
|
960
|
+
this.schema = "tms";
|
|
961
|
+
this.props = props;
|
|
962
|
+
this.url = (0, import_loader_utils.resolvePath)(props.url);
|
|
963
|
+
this.getTileData = this.getTileData.bind(this);
|
|
964
|
+
this.metadata = this.getMetadata();
|
|
965
|
+
}
|
|
966
|
+
// @ts-ignore - Metadata type misalignment
|
|
967
|
+
async getMetadata() {
|
|
968
|
+
var _a, _b;
|
|
969
|
+
const metadataUrl = this.getMetadataUrl();
|
|
970
|
+
const response = await this.fetch(metadataUrl);
|
|
971
|
+
if (!response.ok) {
|
|
972
|
+
return null;
|
|
973
|
+
}
|
|
974
|
+
const tileJSON = await response.text();
|
|
975
|
+
const metadata = ((_b = (_a = import_mvt.TileJSONLoader).parseTextSync) == null ? void 0 : _b.call(_a, JSON.stringify(tileJSON))) || null;
|
|
976
|
+
return metadata;
|
|
977
|
+
}
|
|
978
|
+
async getTile(tileParams) {
|
|
979
|
+
const { x: x2, y: y2, zoom: z } = tileParams;
|
|
980
|
+
const tileUrl = this.getTileURL(x2, y2, z);
|
|
981
|
+
const response = await this.fetch(tileUrl);
|
|
982
|
+
if (!response.ok) {
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
986
|
+
return arrayBuffer;
|
|
987
|
+
}
|
|
988
|
+
// Tile Source interface implementation: deck.gl compatible API
|
|
989
|
+
// TODO - currently only handles image tiles, not vector tiles
|
|
990
|
+
async getTileData(tileParams) {
|
|
991
|
+
const { x: x2, y: y2, z } = tileParams.index;
|
|
992
|
+
const metadata = await this.metadata;
|
|
993
|
+
switch (metadata.mimeType || "application/vnd.mapbox-vector-tile") {
|
|
994
|
+
case "application/vnd.mapbox-vector-tile":
|
|
995
|
+
return await this.getVectorTile({ x: x2, y: y2, zoom: z, layers: [] });
|
|
996
|
+
default:
|
|
997
|
+
return await this.getImageTile({ x: x2, y: y2, zoom: z, layers: [] });
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
// ImageTileSource interface implementation
|
|
1001
|
+
async getImageTile(tileParams) {
|
|
1002
|
+
const arrayBuffer = await this.getTile(tileParams);
|
|
1003
|
+
return arrayBuffer ? await import_images.ImageLoader.parse(arrayBuffer, this.loadOptions) : null;
|
|
1004
|
+
}
|
|
1005
|
+
// VectorTileSource interface implementation
|
|
1006
|
+
async getVectorTile(tileParams) {
|
|
1007
|
+
var _a;
|
|
1008
|
+
const arrayBuffer = await this.getTile(tileParams);
|
|
1009
|
+
const loadOptions = {
|
|
1010
|
+
shape: "geojson-table",
|
|
1011
|
+
mvt: {
|
|
1012
|
+
coordinates: "wgs84",
|
|
1013
|
+
tileIndex: { x: tileParams.x, y: tileParams.y, z: tileParams.zoom },
|
|
1014
|
+
...(_a = this.loadOptions) == null ? void 0 : _a.mvt
|
|
1015
|
+
},
|
|
1016
|
+
...this.loadOptions
|
|
1017
|
+
};
|
|
1018
|
+
return arrayBuffer ? await import_mvt.MVTLoader.parse(arrayBuffer, loadOptions) : null;
|
|
1019
|
+
}
|
|
1020
|
+
getMetadataUrl() {
|
|
1021
|
+
return `${this.url}/tilejson.json`;
|
|
1022
|
+
}
|
|
1023
|
+
getTileURL(x2, y2, z) {
|
|
1024
|
+
switch (this.schema) {
|
|
1025
|
+
case "xyz":
|
|
1026
|
+
return `${this.url}/${x2}/${y2}/${z}`;
|
|
1027
|
+
case "tms":
|
|
1028
|
+
default:
|
|
1029
|
+
return `${this.url}/${z}/${x2}/${y2}`;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
// src/lib/geojson-tiler/simplify.ts
|
|
1035
|
+
function simplify(coords, first, last, sqTolerance) {
|
|
1036
|
+
let maxSqDist = sqTolerance;
|
|
1037
|
+
const mid = last - first >> 1;
|
|
1038
|
+
let minPosToMid = last - first;
|
|
1039
|
+
let index;
|
|
1040
|
+
const ax = coords[first];
|
|
1041
|
+
const ay = coords[first + 1];
|
|
1042
|
+
const bx = coords[last];
|
|
1043
|
+
const by = coords[last + 1];
|
|
1044
|
+
for (let i2 = first + 3; i2 < last; i2 += 3) {
|
|
1045
|
+
const d = getSqSegDist(coords[i2], coords[i2 + 1], ax, ay, bx, by);
|
|
1046
|
+
if (d > maxSqDist) {
|
|
1047
|
+
index = i2;
|
|
1048
|
+
maxSqDist = d;
|
|
1049
|
+
} else if (d === maxSqDist) {
|
|
1050
|
+
const posToMid = Math.abs(i2 - mid);
|
|
1051
|
+
if (posToMid < minPosToMid) {
|
|
1052
|
+
index = i2;
|
|
1053
|
+
minPosToMid = posToMid;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
if (maxSqDist > sqTolerance) {
|
|
1058
|
+
if (index - first > 3)
|
|
1059
|
+
simplify(coords, first, index, sqTolerance);
|
|
1060
|
+
coords[index + 2] = maxSqDist;
|
|
1061
|
+
if (last - index > 3)
|
|
1062
|
+
simplify(coords, index, last, sqTolerance);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
function getSqSegDist(px, py, x2, y2, bx, by) {
|
|
1066
|
+
let dx = bx - x2;
|
|
1067
|
+
let dy = by - y2;
|
|
1068
|
+
if (dx !== 0 || dy !== 0) {
|
|
1069
|
+
const t = ((px - x2) * dx + (py - y2) * dy) / (dx * dx + dy * dy);
|
|
1070
|
+
if (t > 1) {
|
|
1071
|
+
x2 = bx;
|
|
1072
|
+
y2 = by;
|
|
1073
|
+
} else if (t > 0) {
|
|
1074
|
+
x2 += dx * t;
|
|
1075
|
+
y2 += dy * t;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
dx = px - x2;
|
|
1079
|
+
dy = py - y2;
|
|
1080
|
+
return dx * dx + dy * dy;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// src/lib/geojson-tiler/feature.ts
|
|
1084
|
+
function createFeature(id, type, geom, tags) {
|
|
1085
|
+
const feature = {
|
|
1086
|
+
// eslint-disable-next-line
|
|
1087
|
+
id: id == null ? null : id,
|
|
1088
|
+
type,
|
|
1089
|
+
geometry: geom,
|
|
1090
|
+
tags,
|
|
1091
|
+
minX: Infinity,
|
|
1092
|
+
minY: Infinity,
|
|
1093
|
+
maxX: -Infinity,
|
|
1094
|
+
maxY: -Infinity
|
|
1095
|
+
};
|
|
1096
|
+
if (type === "Point" || type === "MultiPoint" || type === "LineString") {
|
|
1097
|
+
calcLineBBox(feature, geom);
|
|
1098
|
+
} else if (type === "Polygon") {
|
|
1099
|
+
calcLineBBox(feature, geom[0]);
|
|
1100
|
+
} else if (type === "MultiLineString") {
|
|
1101
|
+
for (const line of geom) {
|
|
1102
|
+
calcLineBBox(feature, line);
|
|
1103
|
+
}
|
|
1104
|
+
} else if (type === "MultiPolygon") {
|
|
1105
|
+
for (const polygon of geom) {
|
|
1106
|
+
calcLineBBox(feature, polygon[0]);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
return feature;
|
|
1110
|
+
}
|
|
1111
|
+
function calcLineBBox(feature, geom) {
|
|
1112
|
+
for (let i2 = 0; i2 < geom.length; i2 += 3) {
|
|
1113
|
+
feature.minX = Math.min(feature.minX, geom[i2]);
|
|
1114
|
+
feature.minY = Math.min(feature.minY, geom[i2 + 1]);
|
|
1115
|
+
feature.maxX = Math.max(feature.maxX, geom[i2]);
|
|
1116
|
+
feature.maxY = Math.max(feature.maxY, geom[i2 + 1]);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// src/lib/geojson-tiler/convert.ts
|
|
1121
|
+
function convert(data, options) {
|
|
1122
|
+
const features = [];
|
|
1123
|
+
if (data.type === "FeatureCollection") {
|
|
1124
|
+
for (let i2 = 0; i2 < data.features.length; i2++) {
|
|
1125
|
+
convertFeature(features, data.features[i2], options, i2);
|
|
1126
|
+
}
|
|
1127
|
+
} else if (data.type === "Feature") {
|
|
1128
|
+
convertFeature(features, data, options);
|
|
1129
|
+
} else {
|
|
1130
|
+
convertFeature(features, { geometry: data }, options);
|
|
1131
|
+
}
|
|
1132
|
+
return features;
|
|
1133
|
+
}
|
|
1134
|
+
function convertFeature(features, geojson, options, index) {
|
|
1135
|
+
if (!geojson.geometry) {
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
const coords = geojson.geometry.coordinates;
|
|
1139
|
+
const type = geojson.geometry.type;
|
|
1140
|
+
const tolerance = Math.pow(options.tolerance / ((1 << options.maxZoom) * options.extent), 2);
|
|
1141
|
+
let geometry = [];
|
|
1142
|
+
let id = geojson.id;
|
|
1143
|
+
if (options.promoteId) {
|
|
1144
|
+
id = geojson.properties[options.promoteId];
|
|
1145
|
+
} else if (options.generateId) {
|
|
1146
|
+
id = index || 0;
|
|
1147
|
+
}
|
|
1148
|
+
if (type === "Point") {
|
|
1149
|
+
convertPoint(coords, geometry);
|
|
1150
|
+
} else if (type === "MultiPoint") {
|
|
1151
|
+
for (const p of coords) {
|
|
1152
|
+
convertPoint(p, geometry);
|
|
1153
|
+
}
|
|
1154
|
+
} else if (type === "LineString") {
|
|
1155
|
+
convertLine(coords, geometry, tolerance, false);
|
|
1156
|
+
} else if (type === "MultiLineString") {
|
|
1157
|
+
if (options.lineMetrics) {
|
|
1158
|
+
for (const line of coords) {
|
|
1159
|
+
geometry = [];
|
|
1160
|
+
convertLine(line, geometry, tolerance, false);
|
|
1161
|
+
features.push(createFeature(id, "LineString", geometry, geojson.properties));
|
|
1162
|
+
}
|
|
1163
|
+
return;
|
|
1164
|
+
} else {
|
|
1165
|
+
convertLines(coords, geometry, tolerance, false);
|
|
1166
|
+
}
|
|
1167
|
+
} else if (type === "Polygon") {
|
|
1168
|
+
convertLines(coords, geometry, tolerance, true);
|
|
1169
|
+
} else if (type === "MultiPolygon") {
|
|
1170
|
+
for (const polygon of coords) {
|
|
1171
|
+
const newPolygon = [];
|
|
1172
|
+
convertLines(polygon, newPolygon, tolerance, true);
|
|
1173
|
+
geometry.push(newPolygon);
|
|
1174
|
+
}
|
|
1175
|
+
} else if (type === "GeometryCollection") {
|
|
1176
|
+
for (const singleGeometry of geojson.geometry.geometries) {
|
|
1177
|
+
convertFeature(
|
|
1178
|
+
features,
|
|
1179
|
+
{
|
|
1180
|
+
id,
|
|
1181
|
+
geometry: singleGeometry,
|
|
1182
|
+
properties: geojson.properties
|
|
1183
|
+
},
|
|
1184
|
+
options,
|
|
1185
|
+
index
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
return;
|
|
1189
|
+
} else {
|
|
1190
|
+
throw new Error("Input data is not a valid GeoJSON object.");
|
|
1191
|
+
}
|
|
1192
|
+
features.push(createFeature(id, type, geometry, geojson.properties));
|
|
1193
|
+
}
|
|
1194
|
+
function convertPoint(coords, out) {
|
|
1195
|
+
out.push(projectX(coords[0]), projectY(coords[1]), 0);
|
|
1196
|
+
}
|
|
1197
|
+
function convertLine(ring, out, tolerance, isPolygon) {
|
|
1198
|
+
let x0, y0;
|
|
1199
|
+
let size = 0;
|
|
1200
|
+
for (let j = 0; j < ring.length; j++) {
|
|
1201
|
+
const x2 = projectX(ring[j][0]);
|
|
1202
|
+
const y2 = projectY(ring[j][1]);
|
|
1203
|
+
out.push(x2, y2, 0);
|
|
1204
|
+
if (j > 0) {
|
|
1205
|
+
if (isPolygon) {
|
|
1206
|
+
size += (x0 * y2 - x2 * y0) / 2;
|
|
1207
|
+
} else {
|
|
1208
|
+
size += Math.sqrt(Math.pow(x2 - x0, 2) + Math.pow(y2 - y0, 2));
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
x0 = x2;
|
|
1212
|
+
y0 = y2;
|
|
1213
|
+
}
|
|
1214
|
+
const last = out.length - 3;
|
|
1215
|
+
out[2] = 1;
|
|
1216
|
+
simplify(out, 0, last, tolerance);
|
|
1217
|
+
out[last + 2] = 1;
|
|
1218
|
+
out.size = Math.abs(size);
|
|
1219
|
+
out.start = 0;
|
|
1220
|
+
out.end = out.size;
|
|
1221
|
+
}
|
|
1222
|
+
function convertLines(rings, out, tolerance, isPolygon) {
|
|
1223
|
+
for (let i2 = 0; i2 < rings.length; i2++) {
|
|
1224
|
+
const geom = [];
|
|
1225
|
+
convertLine(rings[i2], geom, tolerance, isPolygon);
|
|
1226
|
+
out.push(geom);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
function projectX(x2) {
|
|
1230
|
+
return x2 / 360 + 0.5;
|
|
1231
|
+
}
|
|
1232
|
+
function projectY(y2) {
|
|
1233
|
+
const sin = Math.sin(y2 * Math.PI / 180);
|
|
1234
|
+
const y22 = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI;
|
|
1235
|
+
return y22 < 0 ? 0 : y22 > 1 ? 1 : y22;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// src/lib/geojson-tiler/clip.ts
|
|
1239
|
+
function clip(features, scale, k1, k2, axis, minAll, maxAll, options) {
|
|
1240
|
+
k1 /= scale;
|
|
1241
|
+
k2 /= scale;
|
|
1242
|
+
if (minAll >= k1 && maxAll < k2) {
|
|
1243
|
+
return features;
|
|
1244
|
+
} else if (maxAll < k1 || minAll >= k2) {
|
|
1245
|
+
return null;
|
|
1246
|
+
}
|
|
1247
|
+
const clipped = [];
|
|
1248
|
+
for (const feature of features) {
|
|
1249
|
+
const geometry = feature.geometry;
|
|
1250
|
+
let type = feature.type;
|
|
1251
|
+
const min = axis === 0 ? feature.minX : feature.minY;
|
|
1252
|
+
const max = axis === 0 ? feature.maxX : feature.maxY;
|
|
1253
|
+
if (min >= k1 && max < k2) {
|
|
1254
|
+
clipped.push(feature);
|
|
1255
|
+
continue;
|
|
1256
|
+
} else if (max < k1 || min >= k2) {
|
|
1257
|
+
continue;
|
|
1258
|
+
}
|
|
1259
|
+
let newGeometry = [];
|
|
1260
|
+
if (type === "Point" || type === "MultiPoint") {
|
|
1261
|
+
clipPoints(geometry, newGeometry, k1, k2, axis);
|
|
1262
|
+
} else if (type === "LineString") {
|
|
1263
|
+
clipLine(geometry, newGeometry, k1, k2, axis, false, options.lineMetrics);
|
|
1264
|
+
} else if (type === "MultiLineString") {
|
|
1265
|
+
clipLines(geometry, newGeometry, k1, k2, axis, false);
|
|
1266
|
+
} else if (type === "Polygon") {
|
|
1267
|
+
clipLines(geometry, newGeometry, k1, k2, axis, true);
|
|
1268
|
+
} else if (type === "MultiPolygon") {
|
|
1269
|
+
for (const polygon of geometry) {
|
|
1270
|
+
const newPolygon = [];
|
|
1271
|
+
clipLines(polygon, newPolygon, k1, k2, axis, true);
|
|
1272
|
+
if (newPolygon.length) {
|
|
1273
|
+
newGeometry.push(newPolygon);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
if (newGeometry.length) {
|
|
1278
|
+
if (options.lineMetrics && type === "LineString") {
|
|
1279
|
+
for (const line of newGeometry) {
|
|
1280
|
+
clipped.push(createFeature(feature.id, type, line, feature.tags));
|
|
1281
|
+
}
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
if (type === "LineString" || type === "MultiLineString") {
|
|
1285
|
+
if (newGeometry.length === 1) {
|
|
1286
|
+
type = "LineString";
|
|
1287
|
+
newGeometry = newGeometry[0];
|
|
1288
|
+
} else {
|
|
1289
|
+
type = "MultiLineString";
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
if (type === "Point" || type === "MultiPoint") {
|
|
1293
|
+
type = newGeometry.length === 3 ? "Point" : "MultiPoint";
|
|
1294
|
+
}
|
|
1295
|
+
clipped.push(createFeature(feature.id, type, newGeometry, feature.tags));
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return clipped.length ? clipped : null;
|
|
1299
|
+
}
|
|
1300
|
+
function clipPoints(geom, newGeom, k1, k2, axis) {
|
|
1301
|
+
for (let i2 = 0; i2 < geom.length; i2 += 3) {
|
|
1302
|
+
const a = geom[i2 + axis];
|
|
1303
|
+
if (a >= k1 && a <= k2) {
|
|
1304
|
+
addPoint(newGeom, geom[i2], geom[i2 + 1], geom[i2 + 2]);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
function clipLine(geom, newGeom, k1, k2, axis, isPolygon, trackMetrics) {
|
|
1309
|
+
let slice = newSlice(geom);
|
|
1310
|
+
const intersect = axis === 0 ? intersectX : intersectY;
|
|
1311
|
+
let len = geom.start;
|
|
1312
|
+
let segLen;
|
|
1313
|
+
let t;
|
|
1314
|
+
for (let i2 = 0; i2 < geom.length - 3; i2 += 3) {
|
|
1315
|
+
const ax2 = geom[i2];
|
|
1316
|
+
const ay2 = geom[i2 + 1];
|
|
1317
|
+
const az2 = geom[i2 + 2];
|
|
1318
|
+
const bx = geom[i2 + 3];
|
|
1319
|
+
const by = geom[i2 + 4];
|
|
1320
|
+
const a2 = axis === 0 ? ax2 : ay2;
|
|
1321
|
+
const b = axis === 0 ? bx : by;
|
|
1322
|
+
let exited = false;
|
|
1323
|
+
if (trackMetrics) {
|
|
1324
|
+
segLen = Math.sqrt(Math.pow(ax2 - bx, 2) + Math.pow(ay2 - by, 2));
|
|
1325
|
+
}
|
|
1326
|
+
if (a2 < k1) {
|
|
1327
|
+
if (b > k1) {
|
|
1328
|
+
t = intersect(slice, ax2, ay2, bx, by, k1);
|
|
1329
|
+
if (trackMetrics) {
|
|
1330
|
+
slice.start = len + segLen * t;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
} else if (a2 > k2) {
|
|
1334
|
+
if (b < k2) {
|
|
1335
|
+
t = intersect(slice, ax2, ay2, bx, by, k2);
|
|
1336
|
+
if (trackMetrics) {
|
|
1337
|
+
slice.start = len + segLen * t;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
} else {
|
|
1341
|
+
addPoint(slice, ax2, ay2, az2);
|
|
1342
|
+
}
|
|
1343
|
+
if (b < k1 && a2 >= k1) {
|
|
1344
|
+
t = intersect(slice, ax2, ay2, bx, by, k1);
|
|
1345
|
+
exited = true;
|
|
1346
|
+
}
|
|
1347
|
+
if (b > k2 && a2 <= k2) {
|
|
1348
|
+
t = intersect(slice, ax2, ay2, bx, by, k2);
|
|
1349
|
+
exited = true;
|
|
1350
|
+
}
|
|
1351
|
+
if (!isPolygon && exited) {
|
|
1352
|
+
if (trackMetrics) {
|
|
1353
|
+
slice.end = len + segLen * t;
|
|
1354
|
+
}
|
|
1355
|
+
newGeom.push(slice);
|
|
1356
|
+
slice = newSlice(geom);
|
|
1357
|
+
}
|
|
1358
|
+
if (trackMetrics) {
|
|
1359
|
+
len += segLen;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
let last = geom.length - 3;
|
|
1363
|
+
const ax = geom[last];
|
|
1364
|
+
const ay = geom[last + 1];
|
|
1365
|
+
const az = geom[last + 2];
|
|
1366
|
+
const a = axis === 0 ? ax : ay;
|
|
1367
|
+
if (a >= k1 && a <= k2)
|
|
1368
|
+
addPoint(slice, ax, ay, az);
|
|
1369
|
+
last = slice.length - 3;
|
|
1370
|
+
if (isPolygon && last >= 3 && (slice[last] !== slice[0] || slice[last + 1] !== slice[1])) {
|
|
1371
|
+
addPoint(slice, slice[0], slice[1], slice[2]);
|
|
1372
|
+
}
|
|
1373
|
+
if (slice.length) {
|
|
1374
|
+
newGeom.push(slice);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
function newSlice(line) {
|
|
1378
|
+
const slice = [];
|
|
1379
|
+
slice.size = line.size;
|
|
1380
|
+
slice.start = line.start;
|
|
1381
|
+
slice.end = line.end;
|
|
1382
|
+
return slice;
|
|
1383
|
+
}
|
|
1384
|
+
function clipLines(geom, newGeom, k1, k2, axis, isPolygon) {
|
|
1385
|
+
for (const line of geom) {
|
|
1386
|
+
clipLine(line, newGeom, k1, k2, axis, isPolygon, false);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
function addPoint(out, x2, y2, z) {
|
|
1390
|
+
out.push(x2, y2, z);
|
|
1391
|
+
}
|
|
1392
|
+
function intersectX(out, ax, ay, bx, by, x2) {
|
|
1393
|
+
const t = (x2 - ax) / (bx - ax);
|
|
1394
|
+
addPoint(out, x2, ay + (by - ay) * t, 1);
|
|
1395
|
+
return t;
|
|
1396
|
+
}
|
|
1397
|
+
function intersectY(out, ax, ay, bx, by, y2) {
|
|
1398
|
+
const t = (y2 - ay) / (by - ay);
|
|
1399
|
+
addPoint(out, ax + (bx - ax) * t, y2, 1);
|
|
1400
|
+
return t;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
// src/lib/geojson-tiler/wrap.ts
|
|
1404
|
+
function wrap(features, options) {
|
|
1405
|
+
const buffer = options.buffer / options.extent;
|
|
1406
|
+
let merged = features;
|
|
1407
|
+
const left = clip(features, 1, -1 - buffer, buffer, 0, -1, 2, options);
|
|
1408
|
+
const right = clip(features, 1, 1 - buffer, 2 + buffer, 0, -1, 2, options);
|
|
1409
|
+
if (left || right) {
|
|
1410
|
+
merged = clip(features, 1, -buffer, 1 + buffer, 0, -1, 2, options) || [];
|
|
1411
|
+
if (left) {
|
|
1412
|
+
merged = shiftFeatureCoords(left, 1).concat(merged);
|
|
1413
|
+
}
|
|
1414
|
+
if (right) {
|
|
1415
|
+
merged = merged.concat(shiftFeatureCoords(right, -1));
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
return merged;
|
|
1419
|
+
}
|
|
1420
|
+
function shiftFeatureCoords(features, offset) {
|
|
1421
|
+
const newFeatures = [];
|
|
1422
|
+
for (let i2 = 0; i2 < features.length; i2++) {
|
|
1423
|
+
const feature = features[i2];
|
|
1424
|
+
const type = feature.type;
|
|
1425
|
+
let newGeometry;
|
|
1426
|
+
if (type === "Point" || type === "MultiPoint" || type === "LineString") {
|
|
1427
|
+
newGeometry = shiftCoords(feature.geometry, offset);
|
|
1428
|
+
} else if (type === "MultiLineString" || type === "Polygon") {
|
|
1429
|
+
newGeometry = [];
|
|
1430
|
+
for (const line of feature.geometry) {
|
|
1431
|
+
newGeometry.push(shiftCoords(line, offset));
|
|
1432
|
+
}
|
|
1433
|
+
} else if (type === "MultiPolygon") {
|
|
1434
|
+
newGeometry = [];
|
|
1435
|
+
for (const polygon of feature.geometry) {
|
|
1436
|
+
const newPolygon = [];
|
|
1437
|
+
for (const line of polygon) {
|
|
1438
|
+
newPolygon.push(shiftCoords(line, offset));
|
|
1439
|
+
}
|
|
1440
|
+
newGeometry.push(newPolygon);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
newFeatures.push(createFeature(feature.id, type, newGeometry, feature.tags));
|
|
1444
|
+
}
|
|
1445
|
+
return newFeatures;
|
|
1446
|
+
}
|
|
1447
|
+
function shiftCoords(points, offset) {
|
|
1448
|
+
const newPoints = [];
|
|
1449
|
+
newPoints.size = points.size;
|
|
1450
|
+
if (points.start !== void 0) {
|
|
1451
|
+
newPoints.start = points.start;
|
|
1452
|
+
newPoints.end = points.end;
|
|
1453
|
+
}
|
|
1454
|
+
for (let i2 = 0; i2 < points.length; i2 += 3) {
|
|
1455
|
+
newPoints.push(points[i2] + offset, points[i2 + 1], points[i2 + 2]);
|
|
1456
|
+
}
|
|
1457
|
+
return newPoints;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
// src/lib/geojson-tiler/transform.ts
|
|
1461
|
+
function transformTile(tile, extent) {
|
|
1462
|
+
if (tile.transformed) {
|
|
1463
|
+
return tile;
|
|
1464
|
+
}
|
|
1465
|
+
const z2 = 1 << tile.z;
|
|
1466
|
+
const tx = tile.x;
|
|
1467
|
+
const ty = tile.y;
|
|
1468
|
+
for (const feature of tile.features) {
|
|
1469
|
+
const geom = feature.geometry;
|
|
1470
|
+
const type = feature.type;
|
|
1471
|
+
feature.geometry = [];
|
|
1472
|
+
if (type === 1) {
|
|
1473
|
+
for (let j = 0; j < geom.length; j += 2) {
|
|
1474
|
+
feature.geometry.push(transformPoint(geom[j], geom[j + 1], extent, z2, tx, ty));
|
|
1475
|
+
}
|
|
1476
|
+
} else {
|
|
1477
|
+
for (let j = 0; j < geom.length; j++) {
|
|
1478
|
+
const ring = [];
|
|
1479
|
+
for (let k = 0; k < geom[j].length; k += 2) {
|
|
1480
|
+
ring.push(transformPoint(geom[j][k], geom[j][k + 1], extent, z2, tx, ty));
|
|
1481
|
+
}
|
|
1482
|
+
feature.geometry.push(ring);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
tile.transformed = true;
|
|
1487
|
+
return tile;
|
|
1488
|
+
}
|
|
1489
|
+
function transformPoint(x2, y2, extent, z2, tx, ty) {
|
|
1490
|
+
return [Math.round(extent * (x2 * z2 - tx)), Math.round(extent * (y2 * z2 - ty))];
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// src/lib/geojson-tiler/tile.ts
|
|
1494
|
+
function createTile(features, z, tx, ty, options) {
|
|
1495
|
+
const tolerance = z === options.maxZoom ? 0 : options.tolerance / ((1 << z) * options.extent);
|
|
1496
|
+
const tile = {
|
|
1497
|
+
features: [],
|
|
1498
|
+
numPoints: 0,
|
|
1499
|
+
numSimplified: 0,
|
|
1500
|
+
numFeatures: features.length,
|
|
1501
|
+
source: null,
|
|
1502
|
+
x: tx,
|
|
1503
|
+
y: ty,
|
|
1504
|
+
z,
|
|
1505
|
+
transformed: false,
|
|
1506
|
+
minX: 2,
|
|
1507
|
+
minY: 1,
|
|
1508
|
+
maxX: -1,
|
|
1509
|
+
maxY: 0
|
|
1510
|
+
};
|
|
1511
|
+
for (const feature of features) {
|
|
1512
|
+
addFeature(tile, feature, tolerance, options);
|
|
1513
|
+
}
|
|
1514
|
+
return tile;
|
|
1515
|
+
}
|
|
1516
|
+
function addFeature(tile, feature, tolerance, options) {
|
|
1517
|
+
const geom = feature.geometry;
|
|
1518
|
+
const type = feature.type;
|
|
1519
|
+
const simplified = [];
|
|
1520
|
+
tile.minX = Math.min(tile.minX, feature.minX);
|
|
1521
|
+
tile.minY = Math.min(tile.minY, feature.minY);
|
|
1522
|
+
tile.maxX = Math.max(tile.maxX, feature.maxX);
|
|
1523
|
+
tile.maxY = Math.max(tile.maxY, feature.maxY);
|
|
1524
|
+
if (type === "Point" || type === "MultiPoint") {
|
|
1525
|
+
for (let i2 = 0; i2 < geom.length; i2 += 3) {
|
|
1526
|
+
simplified.push(geom[i2], geom[i2 + 1]);
|
|
1527
|
+
tile.numPoints++;
|
|
1528
|
+
tile.numSimplified++;
|
|
1529
|
+
}
|
|
1530
|
+
} else if (type === "LineString") {
|
|
1531
|
+
addLine(simplified, geom, tile, tolerance, false, false);
|
|
1532
|
+
} else if (type === "MultiLineString" || type === "Polygon") {
|
|
1533
|
+
for (let i2 = 0; i2 < geom.length; i2++) {
|
|
1534
|
+
addLine(simplified, geom[i2], tile, tolerance, type === "Polygon", i2 === 0);
|
|
1535
|
+
}
|
|
1536
|
+
} else if (type === "MultiPolygon") {
|
|
1537
|
+
for (let k = 0; k < geom.length; k++) {
|
|
1538
|
+
const polygon = geom[k];
|
|
1539
|
+
for (let i2 = 0; i2 < polygon.length; i2++) {
|
|
1540
|
+
addLine(simplified, polygon[i2], tile, tolerance, true, i2 === 0);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
if (simplified.length) {
|
|
1545
|
+
let tags = feature.tags || null;
|
|
1546
|
+
if (type === "LineString" && options.lineMetrics) {
|
|
1547
|
+
tags = {};
|
|
1548
|
+
for (const key in feature.tags)
|
|
1549
|
+
tags[key] = feature.tags[key];
|
|
1550
|
+
tags.mapbox_clip_start = geom.start / geom.size;
|
|
1551
|
+
tags.mapbox_clip_end = geom.end / geom.size;
|
|
1552
|
+
}
|
|
1553
|
+
const tileFeature = {
|
|
1554
|
+
geometry: simplified,
|
|
1555
|
+
type: type === "Polygon" || type === "MultiPolygon" ? 3 : type === "LineString" || type === "MultiLineString" ? 2 : 1,
|
|
1556
|
+
tags
|
|
1557
|
+
};
|
|
1558
|
+
if (feature.id !== null) {
|
|
1559
|
+
tileFeature.id = feature.id;
|
|
1560
|
+
}
|
|
1561
|
+
tile.features.push(tileFeature);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
function addLine(result, geom, tile, tolerance, isPolygon, isOuter) {
|
|
1565
|
+
const sqTolerance = tolerance * tolerance;
|
|
1566
|
+
if (tolerance > 0 && geom.size < (isPolygon ? sqTolerance : tolerance)) {
|
|
1567
|
+
tile.numPoints += geom.length / 3;
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
const ring = [];
|
|
1571
|
+
for (let i2 = 0; i2 < geom.length; i2 += 3) {
|
|
1572
|
+
if (tolerance === 0 || geom[i2 + 2] > sqTolerance) {
|
|
1573
|
+
tile.numSimplified++;
|
|
1574
|
+
ring.push(geom[i2], geom[i2 + 1]);
|
|
1575
|
+
}
|
|
1576
|
+
tile.numPoints++;
|
|
1577
|
+
}
|
|
1578
|
+
if (isPolygon)
|
|
1579
|
+
rewind(ring, isOuter);
|
|
1580
|
+
result.push(ring);
|
|
1581
|
+
}
|
|
1582
|
+
function rewind(ring, clockwise) {
|
|
1583
|
+
let area = 0;
|
|
1584
|
+
for (let i2 = 0, j = ring.length - 2; i2 < ring.length; j = i2, i2 += 2) {
|
|
1585
|
+
area += (ring[i2] - ring[j]) * (ring[i2 + 1] + ring[j + 1]);
|
|
1586
|
+
}
|
|
1587
|
+
if (area > 0 === clockwise) {
|
|
1588
|
+
for (let i2 = 0, len = ring.length; i2 < len / 2; i2 += 2) {
|
|
1589
|
+
const x2 = ring[i2];
|
|
1590
|
+
const y2 = ring[i2 + 1];
|
|
1591
|
+
ring[i2] = ring[len - 2 - i2];
|
|
1592
|
+
ring[i2 + 1] = ring[len - 1 - i2];
|
|
1593
|
+
ring[len - 2 - i2] = x2;
|
|
1594
|
+
ring[len - 1 - i2] = y2;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
// src/lib/geojson-tiler/geojson-tiler.ts
|
|
1600
|
+
var DEFAULT_OPTIONS = {
|
|
1601
|
+
maxZoom: 14,
|
|
1602
|
+
// max zoom to preserve detail on
|
|
1603
|
+
indexMaxZoom: 5,
|
|
1604
|
+
// max zoom in the tile index
|
|
1605
|
+
indexMaxPoints: 1e5,
|
|
1606
|
+
// max number of points per tile in the tile index
|
|
1607
|
+
tolerance: 3,
|
|
1608
|
+
// simplification tolerance (higher means simpler)
|
|
1609
|
+
extent: 4096,
|
|
1610
|
+
// tile extent
|
|
1611
|
+
buffer: 64,
|
|
1612
|
+
// tile buffer on each side
|
|
1613
|
+
lineMetrics: false,
|
|
1614
|
+
// whether to calculate line metrics
|
|
1615
|
+
// @ts-expect-error Ensures all these required params have defaults
|
|
1616
|
+
promoteId: void 0,
|
|
1617
|
+
// name of a feature property to be promoted to feature.id
|
|
1618
|
+
generateId: false,
|
|
1619
|
+
// whether to generate feature ids. Cannot be used with promoteId
|
|
1620
|
+
debug: 0
|
|
1621
|
+
// logging level (0, 1 or 2)
|
|
1622
|
+
};
|
|
1623
|
+
var GeoJSONTiler = class {
|
|
1624
|
+
constructor(data, options) {
|
|
1625
|
+
// tiles and tileCoords are part of the public API
|
|
1626
|
+
this.tiles = {};
|
|
1627
|
+
this.tileCoords = [];
|
|
1628
|
+
this.stats = {};
|
|
1629
|
+
this.total = 0;
|
|
1630
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
1631
|
+
options = this.options;
|
|
1632
|
+
const debug = options.debug;
|
|
1633
|
+
if (debug)
|
|
1634
|
+
console.time("preprocess data");
|
|
1635
|
+
if (this.options.maxZoom < 0 || this.options.maxZoom > 24) {
|
|
1636
|
+
throw new Error("maxZoom should be in the 0-24 range");
|
|
1637
|
+
}
|
|
1638
|
+
if (options.promoteId && this.options.generateId) {
|
|
1639
|
+
throw new Error("promoteId and generateId cannot be used together.");
|
|
1640
|
+
}
|
|
1641
|
+
let features = convert(data, options);
|
|
1642
|
+
if (debug) {
|
|
1643
|
+
console.timeEnd("preprocess data");
|
|
1644
|
+
console.log(
|
|
1645
|
+
"index: maxZoom: %d, maxPoints: %d",
|
|
1646
|
+
options.indexMaxZoom,
|
|
1647
|
+
options.indexMaxPoints
|
|
1648
|
+
);
|
|
1649
|
+
console.time("generate tiles");
|
|
1650
|
+
}
|
|
1651
|
+
features = wrap(features, this.options);
|
|
1652
|
+
if (features.length) {
|
|
1653
|
+
this.splitTile(features, 0, 0, 0);
|
|
1654
|
+
}
|
|
1655
|
+
if (debug) {
|
|
1656
|
+
if (features.length) {
|
|
1657
|
+
console.log("features: %d, points: %d", this.tiles[0].numFeatures, this.tiles[0].numPoints);
|
|
1658
|
+
}
|
|
1659
|
+
console.timeEnd("generate tiles");
|
|
1660
|
+
console.log("tiles generated:", this.total, JSON.stringify(this.stats));
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Get a tile at the specified index
|
|
1665
|
+
* @param z
|
|
1666
|
+
* @param x
|
|
1667
|
+
* @param y
|
|
1668
|
+
* @returns
|
|
1669
|
+
*/
|
|
1670
|
+
// eslint-disable-next-line complexity, max-statements
|
|
1671
|
+
getTile(z, x2, y2) {
|
|
1672
|
+
const { extent, debug } = this.options;
|
|
1673
|
+
if (z < 0 || z > 24) {
|
|
1674
|
+
return null;
|
|
1675
|
+
}
|
|
1676
|
+
const z2 = 1 << z;
|
|
1677
|
+
x2 = x2 + z2 & z2 - 1;
|
|
1678
|
+
const id = toID(z, x2, y2);
|
|
1679
|
+
if (this.tiles[id]) {
|
|
1680
|
+
return transformTile(this.tiles[id], extent);
|
|
1681
|
+
}
|
|
1682
|
+
if (debug > 1)
|
|
1683
|
+
console.log("drilling down to z%d-%d-%d", z, x2, y2);
|
|
1684
|
+
let z0 = z;
|
|
1685
|
+
let x0 = x2;
|
|
1686
|
+
let y0 = y2;
|
|
1687
|
+
let parent;
|
|
1688
|
+
while (!parent && z0 > 0) {
|
|
1689
|
+
z0--;
|
|
1690
|
+
x0 = x0 >> 1;
|
|
1691
|
+
y0 = y0 >> 1;
|
|
1692
|
+
parent = this.tiles[toID(z0, x0, y0)];
|
|
1693
|
+
}
|
|
1694
|
+
if (!parent || !parent.source) {
|
|
1695
|
+
return null;
|
|
1696
|
+
}
|
|
1697
|
+
if (debug > 1) {
|
|
1698
|
+
console.log("found parent tile z%d-%d-%d", z0, x0, y0);
|
|
1699
|
+
console.time("drilling down");
|
|
1700
|
+
}
|
|
1701
|
+
this.splitTile(parent.source, z0, x0, y0, z, x2, y2);
|
|
1702
|
+
if (debug > 1) {
|
|
1703
|
+
console.timeEnd("drilling down");
|
|
1704
|
+
}
|
|
1705
|
+
return this.tiles[id] ? transformTile(this.tiles[id], extent) : null;
|
|
1706
|
+
}
|
|
1707
|
+
/**
|
|
1708
|
+
* splits features from a parent tile to sub-tiles.
|
|
1709
|
+
* @param z, x, and y are the coordinates of the parent tile
|
|
1710
|
+
* @param cz, cx, and cy are the coordinates of the target tile
|
|
1711
|
+
*
|
|
1712
|
+
* If no target tile is specified, splitting stops when we reach the maximum
|
|
1713
|
+
* zoom or the number of points is low as specified in the options.
|
|
1714
|
+
*/
|
|
1715
|
+
// eslint-disable-next-line max-params, max-statements, complexity
|
|
1716
|
+
splitTile(features, z, x2, y2, cz, cx, cy) {
|
|
1717
|
+
const stack = [features, z, x2, y2];
|
|
1718
|
+
const options = this.options;
|
|
1719
|
+
const debug = options.debug;
|
|
1720
|
+
while (stack.length) {
|
|
1721
|
+
y2 = stack.pop();
|
|
1722
|
+
x2 = stack.pop();
|
|
1723
|
+
z = stack.pop();
|
|
1724
|
+
features = stack.pop();
|
|
1725
|
+
const z2 = 1 << z;
|
|
1726
|
+
const id = toID(z, x2, y2);
|
|
1727
|
+
let tile = this.tiles[id];
|
|
1728
|
+
if (!tile) {
|
|
1729
|
+
if (debug > 1) {
|
|
1730
|
+
console.time("creation");
|
|
1731
|
+
}
|
|
1732
|
+
tile = this.tiles[id] = createTile(features, z, x2, y2, options);
|
|
1733
|
+
this.tileCoords.push({ z, x: x2, y: y2 });
|
|
1734
|
+
if (debug) {
|
|
1735
|
+
if (debug > 1) {
|
|
1736
|
+
console.log(
|
|
1737
|
+
"tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",
|
|
1738
|
+
z,
|
|
1739
|
+
x2,
|
|
1740
|
+
y2,
|
|
1741
|
+
tile.numFeatures,
|
|
1742
|
+
tile.numPoints,
|
|
1743
|
+
tile.numSimplified
|
|
1744
|
+
);
|
|
1745
|
+
console.timeEnd("creation");
|
|
1746
|
+
}
|
|
1747
|
+
const key = `z${z}`;
|
|
1748
|
+
this.stats[key] = (this.stats[key] || 0) + 1;
|
|
1749
|
+
this.total++;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
tile.source = features;
|
|
1753
|
+
if (cz === void 0) {
|
|
1754
|
+
if (z === options.indexMaxZoom || tile.numPoints <= options.indexMaxPoints)
|
|
1755
|
+
continue;
|
|
1756
|
+
} else if (z === options.maxZoom || z === cz) {
|
|
1757
|
+
continue;
|
|
1758
|
+
} else if (cz !== void 0) {
|
|
1759
|
+
const zoomSteps = cz - z;
|
|
1760
|
+
if (x2 !== cx >> zoomSteps || y2 !== cy >> zoomSteps)
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
tile.source = null;
|
|
1764
|
+
if (features.length === 0)
|
|
1765
|
+
continue;
|
|
1766
|
+
if (debug > 1)
|
|
1767
|
+
console.time("clipping");
|
|
1768
|
+
const k1 = 0.5 * options.buffer / options.extent;
|
|
1769
|
+
const k2 = 0.5 - k1;
|
|
1770
|
+
const k3 = 0.5 + k1;
|
|
1771
|
+
const k4 = 1 + k1;
|
|
1772
|
+
let tl = null;
|
|
1773
|
+
let bl = null;
|
|
1774
|
+
let tr = null;
|
|
1775
|
+
let br = null;
|
|
1776
|
+
let left = clip(features, z2, x2 - k1, x2 + k3, 0, tile.minX, tile.maxX, options);
|
|
1777
|
+
let right = clip(features, z2, x2 + k2, x2 + k4, 0, tile.minX, tile.maxX, options);
|
|
1778
|
+
features = null;
|
|
1779
|
+
if (left) {
|
|
1780
|
+
tl = clip(left, z2, y2 - k1, y2 + k3, 1, tile.minY, tile.maxY, options);
|
|
1781
|
+
bl = clip(left, z2, y2 + k2, y2 + k4, 1, tile.minY, tile.maxY, options);
|
|
1782
|
+
left = null;
|
|
1783
|
+
}
|
|
1784
|
+
if (right) {
|
|
1785
|
+
tr = clip(right, z2, y2 - k1, y2 + k3, 1, tile.minY, tile.maxY, options);
|
|
1786
|
+
br = clip(right, z2, y2 + k2, y2 + k4, 1, tile.minY, tile.maxY, options);
|
|
1787
|
+
right = null;
|
|
1788
|
+
}
|
|
1789
|
+
if (debug > 1)
|
|
1790
|
+
console.timeEnd("clipping");
|
|
1791
|
+
stack.push(tl || [], z + 1, x2 * 2, y2 * 2);
|
|
1792
|
+
stack.push(bl || [], z + 1, x2 * 2, y2 * 2 + 1);
|
|
1793
|
+
stack.push(tr || [], z + 1, x2 * 2 + 1, y2 * 2);
|
|
1794
|
+
stack.push(br || [], z + 1, x2 * 2 + 1, y2 * 2 + 1);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
function toID(z, x2, y2) {
|
|
1799
|
+
return ((1 << z) * y2 + x2) * 32 + z;
|
|
1800
|
+
}
|