@loaders.gl/wkt 4.3.1 → 4.4.0-alpha.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/dist/dist.dev.js +1281 -1266
- package/dist/dist.min.js +2 -2
- package/dist/hex-wkb-loader.d.ts +6 -5
- package/dist/hex-wkb-loader.d.ts.map +1 -1
- package/dist/hex-wkb-loader.js +4 -4
- package/dist/index.cjs +51 -1622
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -5
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/{utils/version.js → version.js} +1 -1
- package/dist/twkb-loader.d.ts +3 -3
- package/dist/twkb-loader.d.ts.map +1 -1
- package/dist/twkb-loader.js +4 -4
- package/dist/twkb-writer.d.ts +2 -1
- package/dist/twkb-writer.d.ts.map +1 -1
- package/dist/twkb-writer.js +5 -4
- package/dist/wkb-loader.d.ts +13 -11
- package/dist/wkb-loader.d.ts.map +1 -1
- package/dist/wkb-loader.js +14 -6
- package/dist/wkb-writer.d.ts +3 -2
- package/dist/wkb-writer.d.ts.map +1 -1
- package/dist/wkb-writer.js +5 -4
- package/dist/wkt-crs-loader.d.ts +1 -1
- package/dist/wkt-crs-loader.d.ts.map +1 -1
- package/dist/wkt-crs-loader.js +2 -2
- package/dist/wkt-crs-writer.d.ts +1 -1
- package/dist/wkt-crs-writer.d.ts.map +1 -1
- package/dist/wkt-crs-writer.js +2 -2
- package/dist/wkt-loader.d.ts +2 -2
- package/dist/wkt-loader.d.ts.map +1 -1
- package/dist/wkt-loader.js +4 -4
- package/dist/wkt-worker.js +26 -13
- package/dist/wkt-writer.d.ts +6 -5
- package/dist/wkt-writer.d.ts.map +1 -1
- package/dist/wkt-writer.js +10 -7
- package/package.json +6 -6
- package/src/hex-wkb-loader.ts +8 -8
- package/src/index.ts +0 -10
- package/src/twkb-loader.ts +5 -5
- package/src/twkb-writer.ts +6 -5
- package/src/wkb-loader.ts +24 -12
- package/src/wkb-writer.ts +8 -7
- package/src/wkt-crs-loader.ts +3 -3
- package/src/wkt-crs-writer.ts +3 -5
- package/src/wkt-loader.ts +6 -5
- package/src/wkt-writer.ts +11 -8
- package/dist/lib/encode-twkb.d.ts +0 -6
- package/dist/lib/encode-twkb.d.ts.map +0 -1
- package/dist/lib/encode-twkb.js +0 -195
- package/dist/lib/encode-wkb.d.ts +0 -33
- package/dist/lib/encode-wkb.d.ts.map +0 -1
- package/dist/lib/encode-wkb.js +0 -286
- package/dist/lib/encode-wkt-crs.d.ts +0 -10
- package/dist/lib/encode-wkt-crs.d.ts.map +0 -1
- package/dist/lib/encode-wkt-crs.js +0 -35
- package/dist/lib/encode-wkt.d.ts +0 -8
- package/dist/lib/encode-wkt.d.ts.map +0 -1
- package/dist/lib/encode-wkt.js +0 -47
- package/dist/lib/parse-hex-wkb.d.ts +0 -1
- package/dist/lib/parse-hex-wkb.d.ts.map +0 -1
- package/dist/lib/parse-hex-wkb.js +0 -1
- package/dist/lib/parse-twkb.d.ts +0 -9
- package/dist/lib/parse-twkb.d.ts.map +0 -1
- package/dist/lib/parse-twkb.js +0 -253
- package/dist/lib/parse-wkb-header.d.ts +0 -39
- package/dist/lib/parse-wkb-header.d.ts.map +0 -1
- package/dist/lib/parse-wkb-header.js +0 -134
- package/dist/lib/parse-wkb.d.ts +0 -5
- package/dist/lib/parse-wkb.d.ts.map +0 -1
- package/dist/lib/parse-wkb.js +0 -241
- package/dist/lib/parse-wkt-crs.d.ts +0 -15
- package/dist/lib/parse-wkt-crs.d.ts.map +0 -1
- package/dist/lib/parse-wkt-crs.js +0 -120
- package/dist/lib/parse-wkt.d.ts +0 -30
- package/dist/lib/parse-wkt.d.ts.map +0 -1
- package/dist/lib/parse-wkt.js +0 -288
- package/dist/lib/utils/base64-encoder.d.ts +0 -5
- package/dist/lib/utils/base64-encoder.d.ts.map +0 -1
- package/dist/lib/utils/base64-encoder.js +0 -153
- package/dist/lib/utils/binary-reader.d.ts +0 -18
- package/dist/lib/utils/binary-reader.d.ts.map +0 -1
- package/dist/lib/utils/binary-reader.js +0 -69
- package/dist/lib/utils/binary-writer.d.ts +0 -28
- package/dist/lib/utils/binary-writer.d.ts.map +0 -1
- package/dist/lib/utils/binary-writer.js +0 -121
- package/dist/lib/utils/hex-encoder.d.ts +0 -15
- package/dist/lib/utils/hex-encoder.d.ts.map +0 -1
- package/dist/lib/utils/hex-encoder.js +0 -54
- package/dist/lib/utils/hex-transcoder.d.ts +0 -15
- package/dist/lib/utils/hex-transcoder.d.ts.map +0 -1
- package/dist/lib/utils/hex-transcoder.js +0 -50
- package/dist/lib/utils/version.d.ts.map +0 -1
- package/src/lib/encode-twkb.ts +0 -308
- package/src/lib/encode-wkb.ts +0 -390
- package/src/lib/encode-wkt-crs.ts +0 -41
- package/src/lib/encode-wkt.ts +0 -56
- package/src/lib/parse-hex-wkb.ts +0 -0
- package/src/lib/parse-twkb.ts +0 -365
- package/src/lib/parse-wkb-header.ts +0 -174
- package/src/lib/parse-wkb.ts +0 -343
- package/src/lib/parse-wkt-crs.ts +0 -149
- package/src/lib/parse-wkt.ts +0 -327
- package/src/lib/utils/base64-encoder.ts +0 -157
- package/src/lib/utils/binary-reader.ts +0 -76
- package/src/lib/utils/binary-writer.ts +0 -127
- package/src/lib/utils/hex-encoder.ts +0 -60
- package/src/lib/utils/hex-transcoder.ts +0 -54
- /package/dist/lib/{utils/version.d.ts → version.d.ts} +0 -0
- /package/src/lib/{utils/version.ts → version.ts} +0 -0
package/dist/dist.dev.js
CHANGED
|
@@ -58,328 +58,579 @@ var __exports__ = (() => {
|
|
|
58
58
|
WKTCRSWriter: () => WKTCRSWriter,
|
|
59
59
|
WKTLoader: () => WKTLoader,
|
|
60
60
|
WKTWorkerLoader: () => WKTWorkerLoader,
|
|
61
|
-
WKTWriter: () => WKTWriter
|
|
62
|
-
decodeHex: () => decodeHex,
|
|
63
|
-
encodeHex: () => encodeHex,
|
|
64
|
-
isTWKB: () => isTWKB,
|
|
65
|
-
isWKB: () => isWKB,
|
|
66
|
-
isWKT: () => isWKT,
|
|
67
|
-
parseWKBHeader: () => parseWKBHeader
|
|
61
|
+
WKTWriter: () => WKTWriter
|
|
68
62
|
});
|
|
69
63
|
__reExport(bundle_exports, __toESM(require_core(), 1));
|
|
70
64
|
|
|
71
|
-
// src/lib/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
84
|
-
if (options?.raw) {
|
|
85
|
-
wkt = wkt.replace(/, {0,2}(-?[\.\d]+)(?=,|\])/g, function(match, p1) {
|
|
86
|
-
return `,"${options?.raw ? "raw:" : ""}${p1}"`;
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
if (options?.debug) {
|
|
90
|
-
console.log(`[wktcrs] json'd wkt: '${wkt}'`);
|
|
65
|
+
// ../gis/src/lib/geometry-converters/convert-binary-geometry-to-geojson.ts
|
|
66
|
+
function convertBinaryGeometryToGeometry(data, startIndex, endIndex) {
|
|
67
|
+
switch (data.type) {
|
|
68
|
+
case "Point":
|
|
69
|
+
return pointToGeoJson(data, startIndex, endIndex);
|
|
70
|
+
case "LineString":
|
|
71
|
+
return lineStringToGeoJson(data, startIndex, endIndex);
|
|
72
|
+
case "Polygon":
|
|
73
|
+
return polygonToGeoJson(data, startIndex, endIndex);
|
|
74
|
+
default:
|
|
75
|
+
const unexpectedInput = data;
|
|
76
|
+
throw new Error(`Unsupported geometry type: ${unexpectedInput?.type}`);
|
|
91
77
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
78
|
+
}
|
|
79
|
+
function polygonToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
|
|
80
|
+
const { positions } = data;
|
|
81
|
+
const polygonIndices = data.polygonIndices.value.filter((x) => x >= startIndex && x <= endIndex);
|
|
82
|
+
const primitivePolygonIndices = data.primitivePolygonIndices.value.filter(
|
|
83
|
+
(x) => x >= startIndex && x <= endIndex
|
|
84
|
+
);
|
|
85
|
+
const multi = polygonIndices.length > 2;
|
|
86
|
+
if (!multi) {
|
|
87
|
+
const coordinates2 = [];
|
|
88
|
+
for (let i = 0; i < primitivePolygonIndices.length - 1; i++) {
|
|
89
|
+
const startRingIndex = primitivePolygonIndices[i];
|
|
90
|
+
const endRingIndex = primitivePolygonIndices[i + 1];
|
|
91
|
+
const ringCoordinates = ringToGeoJson(positions, startRingIndex, endRingIndex);
|
|
92
|
+
coordinates2.push(ringCoordinates);
|
|
93
|
+
}
|
|
94
|
+
return { type: "Polygon", coordinates: coordinates2 };
|
|
98
95
|
}
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
const coordinates = [];
|
|
97
|
+
for (let i = 0; i < polygonIndices.length - 1; i++) {
|
|
98
|
+
const startPolygonIndex = polygonIndices[i];
|
|
99
|
+
const endPolygonIndex = polygonIndices[i + 1];
|
|
100
|
+
const polygonCoordinates = polygonToGeoJson(
|
|
101
|
+
data,
|
|
102
|
+
startPolygonIndex,
|
|
103
|
+
endPolygonIndex
|
|
104
|
+
).coordinates;
|
|
105
|
+
coordinates.push(polygonCoordinates);
|
|
101
106
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
parent[kwarr].push(data2);
|
|
112
|
-
} else if (kw in parent) {
|
|
113
|
-
parent[kwarr] = [parent[kw], data2];
|
|
114
|
-
delete parent[kw];
|
|
115
|
-
} else {
|
|
116
|
-
parent[kw] = data2;
|
|
117
|
-
}
|
|
118
|
-
return parent;
|
|
107
|
+
return { type: "MultiPolygon", coordinates };
|
|
108
|
+
}
|
|
109
|
+
function lineStringToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
|
|
110
|
+
const { positions } = data;
|
|
111
|
+
const pathIndices = data.pathIndices.value.filter((x) => x >= startIndex && x <= endIndex);
|
|
112
|
+
const multi = pathIndices.length > 2;
|
|
113
|
+
if (!multi) {
|
|
114
|
+
const coordinates2 = ringToGeoJson(positions, pathIndices[0], pathIndices[1]);
|
|
115
|
+
return { type: "LineString", coordinates: coordinates2 };
|
|
119
116
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
const coordinates = [];
|
|
118
|
+
for (let i = 0; i < pathIndices.length - 1; i++) {
|
|
119
|
+
const ringCoordinates = ringToGeoJson(positions, pathIndices[i], pathIndices[i + 1]);
|
|
120
|
+
coordinates.push(ringCoordinates);
|
|
123
121
|
}
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
return { type: "MultiLineString", coordinates };
|
|
123
|
+
}
|
|
124
|
+
function pointToGeoJson(data, startIndex, endIndex) {
|
|
125
|
+
const { positions } = data;
|
|
126
|
+
const coordinates = ringToGeoJson(positions, startIndex, endIndex);
|
|
127
|
+
const multi = coordinates.length > 1;
|
|
128
|
+
if (multi) {
|
|
129
|
+
return { type: "MultiPoint", coordinates };
|
|
126
130
|
}
|
|
127
|
-
return
|
|
131
|
+
return { type: "Point", coordinates: coordinates[0] };
|
|
128
132
|
}
|
|
129
|
-
function
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const k = it[0];
|
|
138
|
-
if (!counts[k])
|
|
139
|
-
counts[k] = 0;
|
|
140
|
-
counts[k]++;
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
for (const k in counts) {
|
|
144
|
-
if (counts[k] > 0)
|
|
145
|
-
keywords.push(k);
|
|
146
|
-
}
|
|
133
|
+
function ringToGeoJson(positions, startIndex, endIndex) {
|
|
134
|
+
startIndex = startIndex || 0;
|
|
135
|
+
endIndex = endIndex || positions.value.length / positions.size;
|
|
136
|
+
const ringCoordinates = [];
|
|
137
|
+
for (let j = startIndex; j < endIndex; j++) {
|
|
138
|
+
const coord = Array();
|
|
139
|
+
for (let k = j * positions.size; k < (j + 1) * positions.size; k++) {
|
|
140
|
+
coord.push(Number(positions.value[k]));
|
|
147
141
|
}
|
|
142
|
+
ringCoordinates.push(coord);
|
|
148
143
|
}
|
|
149
|
-
|
|
150
|
-
data[key] = sort(data[key]);
|
|
151
|
-
});
|
|
152
|
-
keywords.forEach((key) => {
|
|
153
|
-
const indices = [];
|
|
154
|
-
const params = [];
|
|
155
|
-
data.forEach((item, i) => {
|
|
156
|
-
if (Array.isArray(item) && item[0] === key) {
|
|
157
|
-
indices.push(i);
|
|
158
|
-
params.push(item);
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
params.sort((a, b) => {
|
|
162
|
-
a = a[1].toString();
|
|
163
|
-
b = b[1].toString();
|
|
164
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
165
|
-
});
|
|
166
|
-
params.forEach((param, i) => {
|
|
167
|
-
data[indices[i]] = param;
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
return data;
|
|
144
|
+
return ringCoordinates;
|
|
171
145
|
}
|
|
172
146
|
|
|
173
|
-
// src/
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
id: "wkt-crs",
|
|
179
|
-
module: "wkt-crs",
|
|
180
|
-
version: VERSION,
|
|
181
|
-
worker: true,
|
|
182
|
-
extensions: [],
|
|
183
|
-
mimeTypes: ["text/plain"],
|
|
184
|
-
category: "json",
|
|
185
|
-
text: true,
|
|
186
|
-
options: {
|
|
187
|
-
"wkt-crs": {}
|
|
188
|
-
},
|
|
189
|
-
parse: async (arrayBuffer, options) => parseWKTCRS(new TextDecoder().decode(arrayBuffer), options?.["wkt-crs"]),
|
|
190
|
-
parseTextSync: (string, options) => parseWKTCRS(string, options?.["wkt-crs"])
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
// src/lib/encode-wkt-crs.ts
|
|
194
|
-
function encodeWKTCRS(wkt, options) {
|
|
195
|
-
if (Array.isArray(wkt) && wkt.length === 1 && Array.isArray(wkt[0])) {
|
|
196
|
-
wkt = wkt[0];
|
|
147
|
+
// ../gis/src/lib/utils/concat-typed-arrays.ts
|
|
148
|
+
function concatTypedArrays(arrays) {
|
|
149
|
+
let byteLength = 0;
|
|
150
|
+
for (let i = 0; i < arrays.length; ++i) {
|
|
151
|
+
byteLength += arrays[i].byteLength;
|
|
197
152
|
}
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (attr.startsWith("raw:")) {
|
|
206
|
-
return attr.replace("raw:", "");
|
|
207
|
-
}
|
|
208
|
-
return `"${attr}"`;
|
|
153
|
+
const buffer = new Uint8Array(byteLength);
|
|
154
|
+
let byteOffset = 0;
|
|
155
|
+
for (let i = 0; i < arrays.length; ++i) {
|
|
156
|
+
const data = new Uint8Array(arrays[i].buffer);
|
|
157
|
+
byteLength = data.length;
|
|
158
|
+
for (let j = 0; j < byteLength; ++j) {
|
|
159
|
+
buffer[byteOffset++] = data[j];
|
|
209
160
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return str;
|
|
161
|
+
}
|
|
162
|
+
return buffer;
|
|
213
163
|
}
|
|
214
164
|
|
|
215
|
-
// src/
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
mimeTypes: ["text/plain"],
|
|
224
|
-
// category: 'json',
|
|
225
|
-
text: true,
|
|
226
|
-
options: {
|
|
227
|
-
"wkt-crs": {}
|
|
228
|
-
},
|
|
229
|
-
encode: async (wktcrs, options) => new TextEncoder().encode(encodeWKTCRS(wktcrs, options?.["wkt-crs"])),
|
|
230
|
-
encodeSync: (wktcrs, options) => new TextEncoder().encode(encodeWKTCRS(wktcrs, options?.["wkt-crs"])),
|
|
231
|
-
encodeTextSync: (wktcrs, options) => encodeWKTCRS(wktcrs, options?.["wkt-crs"])
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// src/lib/parse-wkt.ts
|
|
235
|
-
var numberRegexp = /[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/;
|
|
236
|
-
var tuples = new RegExp("^" + numberRegexp.source + "(\\s" + numberRegexp.source + "){1,}");
|
|
237
|
-
var WKT_MAGIC_STRINGS = [
|
|
238
|
-
"POINT(",
|
|
239
|
-
"LINESTRING(",
|
|
240
|
-
"POLYGON(",
|
|
241
|
-
"MULTIPOINT(",
|
|
242
|
-
"MULTILINESTRING(",
|
|
243
|
-
"MULTIPOLYGON(",
|
|
244
|
-
"GEOMETRYCOLLECTION("
|
|
245
|
-
// We only support this "geojson" subset of the OGC simple features standard
|
|
246
|
-
];
|
|
247
|
-
function isWKT(input) {
|
|
248
|
-
return WKT_MAGIC_STRINGS.some((magicString) => input.startsWith(magicString));
|
|
165
|
+
// ../gis/src/lib/binary-geometry-api/concat-binary-geometry.ts
|
|
166
|
+
function concatenateBinaryPointGeometries(binaryPointGeometries, dimension) {
|
|
167
|
+
const positions = binaryPointGeometries.map((geometry) => geometry.positions.value);
|
|
168
|
+
const concatenatedPositions = new Float64Array(concatTypedArrays(positions).buffer);
|
|
169
|
+
return {
|
|
170
|
+
type: "Point",
|
|
171
|
+
positions: { value: concatenatedPositions, size: dimension }
|
|
172
|
+
};
|
|
249
173
|
}
|
|
250
|
-
function
|
|
251
|
-
|
|
174
|
+
function concatenateBinaryLineGeometries(binaryLineGeometries, dimension) {
|
|
175
|
+
const lines = binaryLineGeometries.map((geometry) => geometry.positions.value);
|
|
176
|
+
const concatenatedPositions = new Float64Array(concatTypedArrays(lines).buffer);
|
|
177
|
+
const pathIndices = lines.map((line) => line.length / dimension).map(cumulativeSum(0));
|
|
178
|
+
pathIndices.unshift(0);
|
|
179
|
+
return {
|
|
180
|
+
type: "LineString",
|
|
181
|
+
positions: { value: concatenatedPositions, size: dimension },
|
|
182
|
+
pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
|
|
183
|
+
};
|
|
252
184
|
}
|
|
253
|
-
function
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
185
|
+
function concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension) {
|
|
186
|
+
const polygons = [];
|
|
187
|
+
const primitivePolygons = [];
|
|
188
|
+
for (const binaryPolygon of binaryPolygonGeometries) {
|
|
189
|
+
const { positions, primitivePolygonIndices: primitivePolygonIndices2 } = binaryPolygon;
|
|
190
|
+
polygons.push(positions.value);
|
|
191
|
+
primitivePolygons.push(primitivePolygonIndices2.value);
|
|
192
|
+
}
|
|
193
|
+
const concatenatedPositions = new Float64Array(concatTypedArrays(polygons).buffer);
|
|
194
|
+
const polygonIndices = polygons.map((p) => p.length / dimension).map(cumulativeSum(0));
|
|
195
|
+
polygonIndices.unshift(0);
|
|
196
|
+
const primitivePolygonIndices = [0];
|
|
197
|
+
for (const primitivePolygon of primitivePolygons) {
|
|
198
|
+
primitivePolygonIndices.push(
|
|
199
|
+
...primitivePolygon.filter((x) => x > 0).map((x) => x + primitivePolygonIndices[primitivePolygonIndices.length - 1])
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
type: "Polygon",
|
|
204
|
+
positions: { value: concatenatedPositions, size: dimension },
|
|
205
|
+
polygonIndices: { value: new Uint32Array(polygonIndices), size: 1 },
|
|
206
|
+
primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
|
|
207
|
+
};
|
|
260
208
|
}
|
|
261
|
-
|
|
262
|
-
|
|
209
|
+
var cumulativeSum = (sum) => (value) => sum += value;
|
|
210
|
+
|
|
211
|
+
// ../gis/src/lib/geometry-converters/wkb/helpers/wkb-types.ts
|
|
212
|
+
var EWKB_FLAG_Z = 2147483648;
|
|
213
|
+
var EWKB_FLAG_M = 1073741824;
|
|
214
|
+
var EWKB_FLAG_SRID = 536870912;
|
|
215
|
+
var MAX_SRID = 1e4;
|
|
216
|
+
var WKT_MAGIC_STRINGS = [
|
|
217
|
+
"POINT(",
|
|
218
|
+
"LINESTRING(",
|
|
219
|
+
"POLYGON(",
|
|
220
|
+
"MULTIPOINT(",
|
|
221
|
+
"MULTILINESTRING(",
|
|
222
|
+
"MULTIPOLYGON(",
|
|
223
|
+
"GEOMETRYCOLLECTION("
|
|
224
|
+
];
|
|
225
|
+
var textEncoder = new TextEncoder();
|
|
226
|
+
var WKT_MAGIC_BYTES = WKT_MAGIC_STRINGS.map((string) => textEncoder.encode(string));
|
|
227
|
+
|
|
228
|
+
// ../gis/src/lib/geometry-converters/wkb/helpers/parse-wkb-header.ts
|
|
229
|
+
function isWKT(input) {
|
|
230
|
+
return getWKTGeometryType(input) !== null;
|
|
263
231
|
}
|
|
264
|
-
function
|
|
265
|
-
if (
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
properties: {
|
|
269
|
-
name: "urn:ogc:def:crs:EPSG::" + srid
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
obj.crs = crs;
|
|
232
|
+
function getWKTGeometryType(input) {
|
|
233
|
+
if (typeof input === "string") {
|
|
234
|
+
const index2 = WKT_MAGIC_STRINGS.findIndex((magicString) => input.startsWith(magicString));
|
|
235
|
+
return index2 >= 0 ? index2 + 1 : null;
|
|
273
236
|
}
|
|
274
|
-
|
|
237
|
+
const inputArray = new Uint8Array(input);
|
|
238
|
+
const index = WKT_MAGIC_BYTES.findIndex(
|
|
239
|
+
(magicBytes) => magicBytes.every((value, index2) => value === inputArray[index2])
|
|
240
|
+
);
|
|
241
|
+
return index >= 0 ? index + 1 : null;
|
|
275
242
|
}
|
|
276
|
-
function
|
|
277
|
-
|
|
278
|
-
|
|
243
|
+
function isTWKB(arrayBuffer) {
|
|
244
|
+
const dataView = new DataView(arrayBuffer);
|
|
245
|
+
const byteOffset = 0;
|
|
246
|
+
const type = dataView.getUint8(byteOffset);
|
|
247
|
+
const geometryType = type & 15;
|
|
248
|
+
if (geometryType < 1 || geometryType > 7) {
|
|
249
|
+
return false;
|
|
279
250
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
function isWKB(arrayBuffer) {
|
|
254
|
+
const dataView = new DataView(arrayBuffer);
|
|
255
|
+
let byteOffset = 0;
|
|
256
|
+
const endianness = dataView.getUint8(byteOffset);
|
|
257
|
+
byteOffset += 1;
|
|
258
|
+
if (endianness > 1) {
|
|
259
|
+
return false;
|
|
283
260
|
}
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
261
|
+
const littleEndian = endianness === 1;
|
|
262
|
+
const geometry = dataView.getUint32(byteOffset, littleEndian);
|
|
263
|
+
byteOffset += 4;
|
|
264
|
+
const geometryType = geometry & 7;
|
|
265
|
+
if (geometryType === 0 || geometryType > 7) {
|
|
266
|
+
return false;
|
|
287
267
|
}
|
|
288
|
-
|
|
289
|
-
if (
|
|
290
|
-
return
|
|
268
|
+
const geometryFlags = geometry - geometryType;
|
|
269
|
+
if (geometryFlags === 0 || geometryFlags === 1e3 || geometryFlags === 2e3 || geometryFlags === 3e3) {
|
|
270
|
+
return true;
|
|
291
271
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
coordinates: c[0]
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
function parseMultiPoint(state) {
|
|
298
|
-
if (!$(/^(MULTIPOINT)/i, state)) {
|
|
299
|
-
return null;
|
|
272
|
+
if ((geometryFlags & ~(EWKB_FLAG_Z | EWKB_FLAG_M | EWKB_FLAG_SRID)) !== 0) {
|
|
273
|
+
return false;
|
|
300
274
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
275
|
+
if (geometryFlags & EWKB_FLAG_SRID) {
|
|
276
|
+
const srid = dataView.getUint32(byteOffset, littleEndian);
|
|
277
|
+
byteOffset += 4;
|
|
278
|
+
if (srid > MAX_SRID) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
307
281
|
}
|
|
308
|
-
|
|
309
|
-
return {
|
|
310
|
-
type: "MultiPoint",
|
|
311
|
-
coordinates: c
|
|
312
|
-
};
|
|
282
|
+
return true;
|
|
313
283
|
}
|
|
314
|
-
function
|
|
315
|
-
|
|
316
|
-
|
|
284
|
+
function parseWKBHeader(dataView, target) {
|
|
285
|
+
const wkbHeader = Object.assign(target || {}, {
|
|
286
|
+
type: "wkb",
|
|
287
|
+
variant: "wkb",
|
|
288
|
+
geometryType: 1,
|
|
289
|
+
dimensions: 2,
|
|
290
|
+
coordinates: "xy",
|
|
291
|
+
littleEndian: true,
|
|
292
|
+
byteOffset: 0
|
|
293
|
+
});
|
|
294
|
+
if (isWKT(dataView.buffer)) {
|
|
295
|
+
throw new Error("WKB: Cannot parse WKT data");
|
|
317
296
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
297
|
+
wkbHeader.littleEndian = dataView.getUint8(wkbHeader.byteOffset) === 1;
|
|
298
|
+
wkbHeader.byteOffset++;
|
|
299
|
+
const geometryCode = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
|
|
300
|
+
wkbHeader.byteOffset += 4;
|
|
301
|
+
wkbHeader.geometryType = geometryCode & 7;
|
|
302
|
+
const isoType = (geometryCode - wkbHeader.geometryType) / 1e3;
|
|
303
|
+
switch (isoType) {
|
|
304
|
+
case 0:
|
|
305
|
+
break;
|
|
306
|
+
case 1:
|
|
307
|
+
wkbHeader.variant = "iso-wkb";
|
|
308
|
+
wkbHeader.dimensions = 3;
|
|
309
|
+
wkbHeader.coordinates = "xyz";
|
|
310
|
+
break;
|
|
311
|
+
case 2:
|
|
312
|
+
wkbHeader.variant = "iso-wkb";
|
|
313
|
+
wkbHeader.dimensions = 3;
|
|
314
|
+
wkbHeader.coordinates = "xym";
|
|
315
|
+
break;
|
|
316
|
+
case 3:
|
|
317
|
+
wkbHeader.variant = "iso-wkb";
|
|
318
|
+
wkbHeader.dimensions = 4;
|
|
319
|
+
wkbHeader.coordinates = "xyzm";
|
|
320
|
+
break;
|
|
321
|
+
default:
|
|
322
|
+
throw new Error(`WKB: Unsupported iso-wkb type: ${isoType}`);
|
|
321
323
|
}
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
324
|
+
const ewkbZ = geometryCode & EWKB_FLAG_Z;
|
|
325
|
+
const ewkbM = geometryCode & EWKB_FLAG_M;
|
|
326
|
+
const ewkbSRID = geometryCode & EWKB_FLAG_SRID;
|
|
327
|
+
if (ewkbZ && ewkbM) {
|
|
328
|
+
wkbHeader.variant = "ewkb";
|
|
329
|
+
wkbHeader.dimensions = 4;
|
|
330
|
+
wkbHeader.coordinates = "xyzm";
|
|
331
|
+
} else if (ewkbZ) {
|
|
332
|
+
wkbHeader.variant = "ewkb";
|
|
333
|
+
wkbHeader.dimensions = 3;
|
|
334
|
+
wkbHeader.coordinates = "xyz";
|
|
335
|
+
} else if (ewkbM) {
|
|
336
|
+
wkbHeader.variant = "ewkb";
|
|
337
|
+
wkbHeader.dimensions = 3;
|
|
338
|
+
wkbHeader.coordinates = "xym";
|
|
325
339
|
}
|
|
326
|
-
if (
|
|
327
|
-
|
|
340
|
+
if (ewkbSRID) {
|
|
341
|
+
wkbHeader.variant = "ewkb";
|
|
342
|
+
wkbHeader.srid = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
|
|
343
|
+
wkbHeader.byteOffset += 4;
|
|
328
344
|
}
|
|
329
|
-
return
|
|
330
|
-
type: "LineString",
|
|
331
|
-
coordinates: c
|
|
332
|
-
};
|
|
345
|
+
return wkbHeader;
|
|
333
346
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
347
|
+
|
|
348
|
+
// ../gis/src/lib/geometry-converters/wkb/convert-wkb-to-binary-geometry.ts
|
|
349
|
+
function convertWKBToBinaryGeometry(arrayBuffer) {
|
|
350
|
+
const dataView = new DataView(arrayBuffer);
|
|
351
|
+
const wkbHeader = parseWKBHeader(dataView);
|
|
352
|
+
const { geometryType, dimensions, littleEndian } = wkbHeader;
|
|
353
|
+
const offset = wkbHeader.byteOffset;
|
|
354
|
+
switch (geometryType) {
|
|
355
|
+
case 1 /* Point */:
|
|
356
|
+
const point = parsePoint(dataView, offset, dimensions, littleEndian);
|
|
357
|
+
return point.geometry;
|
|
358
|
+
case 2 /* LineString */:
|
|
359
|
+
const line = parseLineString(dataView, offset, dimensions, littleEndian);
|
|
360
|
+
return line.geometry;
|
|
361
|
+
case 3 /* Polygon */:
|
|
362
|
+
const polygon = parsePolygon(dataView, offset, dimensions, littleEndian);
|
|
363
|
+
return polygon.geometry;
|
|
364
|
+
case 4 /* MultiPoint */:
|
|
365
|
+
const multiPoint = parseMultiPoint(dataView, offset, dimensions, littleEndian);
|
|
366
|
+
multiPoint.type = "Point";
|
|
367
|
+
return multiPoint;
|
|
368
|
+
case 5 /* MultiLineString */:
|
|
369
|
+
const multiLine = parseMultiLineString(dataView, offset, dimensions, littleEndian);
|
|
370
|
+
multiLine.type = "LineString";
|
|
371
|
+
return multiLine;
|
|
372
|
+
case 6 /* MultiPolygon */:
|
|
373
|
+
const multiPolygon = parseMultiPolygon(dataView, offset, dimensions, littleEndian);
|
|
374
|
+
multiPolygon.type = "Polygon";
|
|
375
|
+
return multiPolygon;
|
|
376
|
+
default:
|
|
377
|
+
throw new Error(`WKB: Unsupported geometry type: ${geometryType}`);
|
|
341
378
|
}
|
|
342
|
-
white(state);
|
|
343
|
-
return {
|
|
344
|
-
// @ts-ignore
|
|
345
|
-
type: "MultiLineString",
|
|
346
|
-
// @ts-expect-error
|
|
347
|
-
coordinates: c
|
|
348
|
-
};
|
|
349
379
|
}
|
|
350
|
-
function
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const c = multicoords(state);
|
|
356
|
-
if (!c) {
|
|
357
|
-
return null;
|
|
380
|
+
function parsePoint(dataView, offset, dimension, littleEndian) {
|
|
381
|
+
const positions = new Float64Array(dimension);
|
|
382
|
+
for (let i = 0; i < dimension; i++) {
|
|
383
|
+
positions[i] = dataView.getFloat64(offset, littleEndian);
|
|
384
|
+
offset += 8;
|
|
358
385
|
}
|
|
359
386
|
return {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
// @ts-expect-error
|
|
363
|
-
coordinates: c
|
|
387
|
+
geometry: { type: "Point", positions: { value: positions, size: dimension } },
|
|
388
|
+
offset
|
|
364
389
|
};
|
|
365
390
|
}
|
|
366
|
-
function
|
|
367
|
-
|
|
368
|
-
|
|
391
|
+
function parseLineString(dataView, offset, dimension, littleEndian) {
|
|
392
|
+
const nPoints = dataView.getUint32(offset, littleEndian);
|
|
393
|
+
offset += 4;
|
|
394
|
+
const positions = new Float64Array(nPoints * dimension);
|
|
395
|
+
for (let i = 0; i < nPoints * dimension; i++) {
|
|
396
|
+
positions[i] = dataView.getFloat64(offset, littleEndian);
|
|
397
|
+
offset += 8;
|
|
369
398
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
return null;
|
|
399
|
+
const pathIndices = [0];
|
|
400
|
+
if (nPoints > 0) {
|
|
401
|
+
pathIndices.push(nPoints);
|
|
374
402
|
}
|
|
375
403
|
return {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
404
|
+
geometry: {
|
|
405
|
+
type: "LineString",
|
|
406
|
+
positions: { value: positions, size: dimension },
|
|
407
|
+
pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
|
|
408
|
+
},
|
|
409
|
+
offset
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
var cumulativeSum2 = (sum) => (value) => sum += value;
|
|
413
|
+
function parsePolygon(dataView, offset, dimension, littleEndian) {
|
|
414
|
+
const nRings = dataView.getUint32(offset, littleEndian);
|
|
415
|
+
offset += 4;
|
|
416
|
+
const rings = [];
|
|
417
|
+
for (let i = 0; i < nRings; i++) {
|
|
418
|
+
const parsed = parseLineString(dataView, offset, dimension, littleEndian);
|
|
419
|
+
const { positions } = parsed.geometry;
|
|
420
|
+
offset = parsed.offset;
|
|
421
|
+
rings.push(positions.value);
|
|
422
|
+
}
|
|
423
|
+
const concatenatedPositions = new Float64Array(concatTypedArrays(rings).buffer);
|
|
424
|
+
const polygonIndices = [0];
|
|
425
|
+
if (concatenatedPositions.length > 0) {
|
|
426
|
+
polygonIndices.push(concatenatedPositions.length / dimension);
|
|
427
|
+
}
|
|
428
|
+
const primitivePolygonIndices = rings.map((l) => l.length / dimension).map(cumulativeSum2(0));
|
|
429
|
+
primitivePolygonIndices.unshift(0);
|
|
430
|
+
return {
|
|
431
|
+
geometry: {
|
|
432
|
+
type: "Polygon",
|
|
433
|
+
positions: { value: concatenatedPositions, size: dimension },
|
|
434
|
+
polygonIndices: {
|
|
435
|
+
value: new Uint32Array(polygonIndices),
|
|
436
|
+
size: 1
|
|
437
|
+
},
|
|
438
|
+
primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
|
|
439
|
+
},
|
|
440
|
+
offset
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function parseMultiPoint(dataView, offset, dimension, littleEndian) {
|
|
444
|
+
const nPoints = dataView.getUint32(offset, littleEndian);
|
|
445
|
+
offset += 4;
|
|
446
|
+
const binaryPointGeometries = [];
|
|
447
|
+
for (let i = 0; i < nPoints; i++) {
|
|
448
|
+
const littleEndianPoint = dataView.getUint8(offset) === 1;
|
|
449
|
+
offset++;
|
|
450
|
+
if (dataView.getUint32(offset, littleEndianPoint) % 1e3 !== 1) {
|
|
451
|
+
throw new Error("WKB: Inner geometries of MultiPoint not of type Point");
|
|
452
|
+
}
|
|
453
|
+
offset += 4;
|
|
454
|
+
const parsed = parsePoint(dataView, offset, dimension, littleEndianPoint);
|
|
455
|
+
offset = parsed.offset;
|
|
456
|
+
binaryPointGeometries.push(parsed.geometry);
|
|
457
|
+
}
|
|
458
|
+
return concatenateBinaryPointGeometries(binaryPointGeometries, dimension);
|
|
459
|
+
}
|
|
460
|
+
function parseMultiLineString(dataView, offset, dimension, littleEndian) {
|
|
461
|
+
const nLines = dataView.getUint32(offset, littleEndian);
|
|
462
|
+
offset += 4;
|
|
463
|
+
const binaryLineGeometries = [];
|
|
464
|
+
for (let i = 0; i < nLines; i++) {
|
|
465
|
+
const littleEndianLine = dataView.getUint8(offset) === 1;
|
|
466
|
+
offset++;
|
|
467
|
+
if (dataView.getUint32(offset, littleEndianLine) % 1e3 !== 2) {
|
|
468
|
+
throw new Error("WKB: Inner geometries of MultiLineString not of type LineString");
|
|
469
|
+
}
|
|
470
|
+
offset += 4;
|
|
471
|
+
const parsed = parseLineString(dataView, offset, dimension, littleEndianLine);
|
|
472
|
+
offset = parsed.offset;
|
|
473
|
+
binaryLineGeometries.push(parsed.geometry);
|
|
474
|
+
}
|
|
475
|
+
return concatenateBinaryLineGeometries(binaryLineGeometries, dimension);
|
|
476
|
+
}
|
|
477
|
+
function parseMultiPolygon(dataView, offset, dimension, littleEndian) {
|
|
478
|
+
const nPolygons = dataView.getUint32(offset, littleEndian);
|
|
479
|
+
offset += 4;
|
|
480
|
+
const binaryPolygonGeometries = [];
|
|
481
|
+
for (let i = 0; i < nPolygons; i++) {
|
|
482
|
+
const littleEndianPolygon = dataView.getUint8(offset) === 1;
|
|
483
|
+
offset++;
|
|
484
|
+
if (dataView.getUint32(offset, littleEndianPolygon) % 1e3 !== 3) {
|
|
485
|
+
throw new Error("WKB: Inner geometries of MultiPolygon not of type Polygon");
|
|
486
|
+
}
|
|
487
|
+
offset += 4;
|
|
488
|
+
const parsed = parsePolygon(dataView, offset, dimension, littleEndianPolygon);
|
|
489
|
+
offset = parsed.offset;
|
|
490
|
+
binaryPolygonGeometries.push(parsed.geometry);
|
|
491
|
+
}
|
|
492
|
+
return concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ../gis/src/lib/geometry-converters/wkb/convert-wkb-to-geometry.ts
|
|
496
|
+
function convertWKBToGeometry(arrayBuffer) {
|
|
497
|
+
const binaryGeometry = convertWKBToBinaryGeometry(arrayBuffer);
|
|
498
|
+
return convertBinaryGeometryToGeometry(binaryGeometry);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// ../gis/src/lib/geometry-converters/wkb/convert-wkt-to-geometry.ts
|
|
502
|
+
var numberRegexp = /[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/;
|
|
503
|
+
var tuples = new RegExp("^" + numberRegexp.source + "(\\s" + numberRegexp.source + "){1,}");
|
|
504
|
+
function convertWKTToGeometry(input, options) {
|
|
505
|
+
const parts = input.split(";");
|
|
506
|
+
let _ = parts.pop();
|
|
507
|
+
const srid = (parts.shift() || "").split("=").pop();
|
|
508
|
+
const state = { parts, _, i: 0 };
|
|
509
|
+
const geometry = parseGeometry(state);
|
|
510
|
+
return options?.wkt?.crs ? addCRS(geometry, srid) : geometry;
|
|
511
|
+
}
|
|
512
|
+
function parseGeometry(state) {
|
|
513
|
+
return parsePoint2(state) || parseLineString2(state) || parsePolygon2(state) || parseMultiPoint2(state) || parseMultiLineString2(state) || parseMultiPolygon2(state) || parseGeometryCollection(state);
|
|
514
|
+
}
|
|
515
|
+
function addCRS(obj, srid) {
|
|
516
|
+
if (obj && srid?.match(/\d+/)) {
|
|
517
|
+
const crs = {
|
|
518
|
+
type: "name",
|
|
519
|
+
properties: {
|
|
520
|
+
name: "urn:ogc:def:crs:EPSG::" + srid
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
obj.crs = crs;
|
|
524
|
+
}
|
|
525
|
+
return obj;
|
|
526
|
+
}
|
|
527
|
+
function parsePoint2(state) {
|
|
528
|
+
if (!$(/^(POINT(\sz)?)/i, state)) {
|
|
529
|
+
return null;
|
|
530
|
+
}
|
|
531
|
+
white(state);
|
|
532
|
+
if (!$(/^(\()/, state)) {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
const c = coords(state);
|
|
536
|
+
if (!c) {
|
|
537
|
+
return null;
|
|
538
|
+
}
|
|
539
|
+
white(state);
|
|
540
|
+
if (!$(/^(\))/, state)) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
return {
|
|
544
|
+
type: "Point",
|
|
545
|
+
coordinates: c[0]
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function parseMultiPoint2(state) {
|
|
549
|
+
if (!$(/^(MULTIPOINT)/i, state)) {
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
white(state);
|
|
553
|
+
const newCoordsFormat = state._?.substring(state._?.indexOf("(") + 1, state._.length - 1).replace(/\(/g, "").replace(/\)/g, "");
|
|
554
|
+
state._ = "MULTIPOINT (" + newCoordsFormat + ")";
|
|
555
|
+
const c = multicoords(state);
|
|
556
|
+
if (!c) {
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
white(state);
|
|
560
|
+
return {
|
|
561
|
+
type: "MultiPoint",
|
|
562
|
+
coordinates: c
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function parseLineString2(state) {
|
|
566
|
+
if (!$(/^(LINESTRING(\sz)?)/i, state)) {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
white(state);
|
|
570
|
+
if (!$(/^(\()/, state)) {
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
const c = coords(state);
|
|
574
|
+
if (!c) {
|
|
575
|
+
return null;
|
|
576
|
+
}
|
|
577
|
+
if (!$(/^(\))/, state)) {
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
return {
|
|
581
|
+
type: "LineString",
|
|
582
|
+
coordinates: c
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
function parseMultiLineString2(state) {
|
|
586
|
+
if (!$(/^(MULTILINESTRING)/i, state))
|
|
587
|
+
return null;
|
|
588
|
+
white(state);
|
|
589
|
+
const c = multicoords(state);
|
|
590
|
+
if (!c) {
|
|
591
|
+
return null;
|
|
592
|
+
}
|
|
593
|
+
white(state);
|
|
594
|
+
return {
|
|
595
|
+
// @ts-ignore
|
|
596
|
+
type: "MultiLineString",
|
|
597
|
+
// @ts-expect-error
|
|
598
|
+
coordinates: c
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
function parsePolygon2(state) {
|
|
602
|
+
if (!$(/^(POLYGON(\sz)?)/i, state)) {
|
|
603
|
+
return null;
|
|
604
|
+
}
|
|
605
|
+
white(state);
|
|
606
|
+
const c = multicoords(state);
|
|
607
|
+
if (!c) {
|
|
608
|
+
return null;
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
// @ts-ignore
|
|
612
|
+
type: "Polygon",
|
|
613
|
+
// @ts-expect-error
|
|
614
|
+
coordinates: c
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
function parseMultiPolygon2(state) {
|
|
618
|
+
if (!$(/^(MULTIPOLYGON)/i, state)) {
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
white(state);
|
|
622
|
+
const c = multicoords(state);
|
|
623
|
+
if (!c) {
|
|
624
|
+
return null;
|
|
625
|
+
}
|
|
626
|
+
return {
|
|
627
|
+
type: "MultiPolygon",
|
|
628
|
+
// @ts-expect-error
|
|
629
|
+
coordinates: c
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
function parseGeometryCollection(state) {
|
|
633
|
+
const geometries = [];
|
|
383
634
|
let geometry;
|
|
384
635
|
if (!$(/^(GEOMETRYCOLLECTION)/i, state)) {
|
|
385
636
|
return null;
|
|
@@ -472,520 +723,319 @@ var __exports__ = (() => {
|
|
|
472
723
|
$(/^\s*/, state);
|
|
473
724
|
}
|
|
474
725
|
|
|
475
|
-
// src/
|
|
476
|
-
var
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
category: "geometry",
|
|
487
|
-
text: true,
|
|
488
|
-
tests: WKT_MAGIC_STRINGS,
|
|
489
|
-
testText: isWKT,
|
|
490
|
-
options: {
|
|
491
|
-
wkt: {
|
|
492
|
-
shape: "geojson-geometry",
|
|
493
|
-
crs: true
|
|
494
|
-
}
|
|
726
|
+
// ../gis/src/lib/utils/binary-reader.ts
|
|
727
|
+
var BinaryReader = class {
|
|
728
|
+
arrayBuffer;
|
|
729
|
+
dataView;
|
|
730
|
+
byteOffset;
|
|
731
|
+
littleEndian;
|
|
732
|
+
constructor(arrayBuffer, isBigEndian = false) {
|
|
733
|
+
this.arrayBuffer = arrayBuffer;
|
|
734
|
+
this.dataView = new DataView(arrayBuffer);
|
|
735
|
+
this.byteOffset = 0;
|
|
736
|
+
this.littleEndian = !isBigEndian;
|
|
495
737
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
parseTextSync: (string, options) => parseWKT(string, options)
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
// src/lib/encode-wkt.ts
|
|
504
|
-
function encodeWKT(geometry) {
|
|
505
|
-
if (geometry.type === "Feature") {
|
|
506
|
-
geometry = geometry.geometry;
|
|
738
|
+
readUInt8() {
|
|
739
|
+
const value = this.dataView.getUint8(this.byteOffset);
|
|
740
|
+
this.byteOffset += 1;
|
|
741
|
+
return value;
|
|
507
742
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
return `LINESTRING ${wrapParens(ringWKT(geometry.coordinates))}`;
|
|
513
|
-
case "Polygon":
|
|
514
|
-
return `POLYGON ${wrapParens(ringsWKT(geometry.coordinates))}`;
|
|
515
|
-
case "MultiPoint":
|
|
516
|
-
return `MULTIPOINT ${wrapParens(ringWKT(geometry.coordinates))}`;
|
|
517
|
-
case "MultiPolygon":
|
|
518
|
-
return `MULTIPOLYGON ${wrapParens(multiRingsWKT(geometry.coordinates))}`;
|
|
519
|
-
case "MultiLineString":
|
|
520
|
-
return `MULTILINESTRING ${wrapParens(ringsWKT(geometry.coordinates))}`;
|
|
521
|
-
case "GeometryCollection":
|
|
522
|
-
return `GEOMETRYCOLLECTION ${wrapParens(geometry.geometries.map(encodeWKT).join(", "))}`;
|
|
523
|
-
default:
|
|
524
|
-
throw new Error("stringify requires a valid GeoJSON Feature or geometry object as input");
|
|
743
|
+
readUInt16() {
|
|
744
|
+
const value = this.dataView.getUint16(this.byteOffset, this.littleEndian);
|
|
745
|
+
this.byteOffset += 2;
|
|
746
|
+
return value;
|
|
525
747
|
}
|
|
748
|
+
readUInt32() {
|
|
749
|
+
const value = this.dataView.getUint32(this.byteOffset, this.littleEndian);
|
|
750
|
+
this.byteOffset += 4;
|
|
751
|
+
return value;
|
|
752
|
+
}
|
|
753
|
+
readInt8() {
|
|
754
|
+
const value = this.dataView.getInt8(this.byteOffset);
|
|
755
|
+
this.byteOffset += 1;
|
|
756
|
+
return value;
|
|
757
|
+
}
|
|
758
|
+
readInt16() {
|
|
759
|
+
const value = this.dataView.getInt16(this.byteOffset, this.littleEndian);
|
|
760
|
+
this.byteOffset += 2;
|
|
761
|
+
return value;
|
|
762
|
+
}
|
|
763
|
+
readInt32() {
|
|
764
|
+
const value = this.dataView.getInt32(this.byteOffset, this.littleEndian);
|
|
765
|
+
this.byteOffset += 4;
|
|
766
|
+
return value;
|
|
767
|
+
}
|
|
768
|
+
readFloat() {
|
|
769
|
+
const value = this.dataView.getFloat32(this.byteOffset, this.littleEndian);
|
|
770
|
+
this.byteOffset += 4;
|
|
771
|
+
return value;
|
|
772
|
+
}
|
|
773
|
+
readDouble() {
|
|
774
|
+
const value = this.dataView.getFloat64(this.byteOffset, this.littleEndian);
|
|
775
|
+
this.byteOffset += 8;
|
|
776
|
+
return value;
|
|
777
|
+
}
|
|
778
|
+
readVarInt() {
|
|
779
|
+
let result = 0;
|
|
780
|
+
let bytesRead = 0;
|
|
781
|
+
let nextByte;
|
|
782
|
+
do {
|
|
783
|
+
nextByte = this.dataView.getUint8(this.byteOffset + bytesRead);
|
|
784
|
+
result += (nextByte & 127) << 7 * bytesRead;
|
|
785
|
+
bytesRead++;
|
|
786
|
+
} while (nextByte >= 128);
|
|
787
|
+
this.byteOffset += bytesRead;
|
|
788
|
+
return result;
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
// ../gis/src/lib/geometry-converters/wkb/convert-twkb-to-geometry.ts
|
|
793
|
+
function convertTWKBToGeometry(arrayBuffer) {
|
|
794
|
+
const binaryReader = new BinaryReader(arrayBuffer);
|
|
795
|
+
const context = parseTWKBHeader(binaryReader);
|
|
796
|
+
if (context.hasSizeAttribute) {
|
|
797
|
+
binaryReader.readVarInt();
|
|
798
|
+
}
|
|
799
|
+
if (context.hasBoundingBox) {
|
|
800
|
+
let dimensions = 2;
|
|
801
|
+
if (context.hasZ) {
|
|
802
|
+
dimensions++;
|
|
803
|
+
}
|
|
804
|
+
if (context.hasM) {
|
|
805
|
+
dimensions++;
|
|
806
|
+
}
|
|
807
|
+
for (let i = 0; i < dimensions; i++) {
|
|
808
|
+
binaryReader.readVarInt();
|
|
809
|
+
binaryReader.readVarInt();
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return parseGeometry2(binaryReader, context, context.geometryType);
|
|
526
813
|
}
|
|
527
|
-
function
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
814
|
+
function parseTWKBHeader(binaryReader) {
|
|
815
|
+
const type = binaryReader.readUInt8();
|
|
816
|
+
const metadataHeader = binaryReader.readUInt8();
|
|
817
|
+
const geometryType = type & 15;
|
|
818
|
+
const precision = zigZagDecode(type >> 4);
|
|
819
|
+
const hasExtendedPrecision = Boolean(metadataHeader >> 3 & 1);
|
|
820
|
+
let hasZ = false;
|
|
821
|
+
let hasM = false;
|
|
822
|
+
let zPrecision = 0;
|
|
823
|
+
let zPrecisionFactor = 1;
|
|
824
|
+
let mPrecision = 0;
|
|
825
|
+
let mPrecisionFactor = 1;
|
|
826
|
+
if (hasExtendedPrecision) {
|
|
827
|
+
const extendedPrecision = binaryReader.readUInt8();
|
|
828
|
+
hasZ = (extendedPrecision & 1) === 1;
|
|
829
|
+
hasM = (extendedPrecision & 2) === 2;
|
|
830
|
+
zPrecision = zigZagDecode((extendedPrecision & 28) >> 2);
|
|
831
|
+
zPrecisionFactor = Math.pow(10, zPrecision);
|
|
832
|
+
mPrecision = zigZagDecode((extendedPrecision & 224) >> 5);
|
|
833
|
+
mPrecisionFactor = Math.pow(10, mPrecision);
|
|
834
|
+
}
|
|
835
|
+
return {
|
|
836
|
+
geometryType,
|
|
837
|
+
precision,
|
|
838
|
+
precisionFactor: Math.pow(10, precision),
|
|
839
|
+
hasBoundingBox: Boolean(metadataHeader >> 0 & 1),
|
|
840
|
+
hasSizeAttribute: Boolean(metadataHeader >> 1 & 1),
|
|
841
|
+
hasIdList: Boolean(metadataHeader >> 2 & 1),
|
|
842
|
+
hasExtendedPrecision,
|
|
843
|
+
isEmpty: Boolean(metadataHeader >> 4 & 1),
|
|
844
|
+
hasZ,
|
|
845
|
+
hasM,
|
|
846
|
+
zPrecision,
|
|
847
|
+
zPrecisionFactor,
|
|
848
|
+
mPrecision,
|
|
849
|
+
mPrecisionFactor
|
|
850
|
+
};
|
|
538
851
|
}
|
|
539
|
-
function
|
|
540
|
-
|
|
852
|
+
function parseGeometry2(binaryReader, context, geometryType) {
|
|
853
|
+
switch (geometryType) {
|
|
854
|
+
case 1 /* Point */:
|
|
855
|
+
return parsePoint3(binaryReader, context);
|
|
856
|
+
case 2 /* LineString */:
|
|
857
|
+
return parseLineString3(binaryReader, context);
|
|
858
|
+
case 3 /* Polygon */:
|
|
859
|
+
return parsePolygon3(binaryReader, context);
|
|
860
|
+
case 4 /* MultiPoint */:
|
|
861
|
+
return parseMultiPoint3(binaryReader, context);
|
|
862
|
+
case 5 /* MultiLineString */:
|
|
863
|
+
return parseMultiLineString3(binaryReader, context);
|
|
864
|
+
case 6 /* MultiPolygon */:
|
|
865
|
+
return parseMultiPolygon3(binaryReader, context);
|
|
866
|
+
case 7 /* GeometryCollection */:
|
|
867
|
+
return parseGeometryCollection2(binaryReader, context);
|
|
868
|
+
default:
|
|
869
|
+
throw new Error(`GeometryType ${geometryType} not supported`);
|
|
870
|
+
}
|
|
541
871
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
name: "WKT (Well Known Text)",
|
|
546
|
-
id: "wkt",
|
|
547
|
-
module: "wkt",
|
|
548
|
-
version: VERSION,
|
|
549
|
-
extensions: ["wkt"],
|
|
550
|
-
text: true,
|
|
551
|
-
encode: async (geometry) => encodeWKTSync(geometry),
|
|
552
|
-
encodeSync: encodeWKTSync,
|
|
553
|
-
encodeTextSync: encodeWKT,
|
|
554
|
-
options: {
|
|
555
|
-
wkt: {}
|
|
872
|
+
function parsePoint3(reader, context) {
|
|
873
|
+
if (context.isEmpty) {
|
|
874
|
+
return { type: "Point", coordinates: [] };
|
|
556
875
|
}
|
|
557
|
-
|
|
558
|
-
function encodeWKTSync(geometry) {
|
|
559
|
-
return new TextEncoder().encode(encodeWKT(geometry)).buffer;
|
|
876
|
+
return { type: "Point", coordinates: readFirstPoint(reader, context) };
|
|
560
877
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
return polygonToGeoJson(data, startIndex, endIndex);
|
|
571
|
-
default:
|
|
572
|
-
const unexpectedInput = data;
|
|
573
|
-
throw new Error(`Unsupported geometry type: ${unexpectedInput?.type}`);
|
|
878
|
+
function parseLineString3(reader, context) {
|
|
879
|
+
if (context.isEmpty) {
|
|
880
|
+
return { type: "LineString", coordinates: [] };
|
|
881
|
+
}
|
|
882
|
+
const pointCount = reader.readVarInt();
|
|
883
|
+
const previousPoint = makePreviousPoint(context);
|
|
884
|
+
const points = [];
|
|
885
|
+
for (let i = 0; i < pointCount; i++) {
|
|
886
|
+
points.push(parseNextPoint(reader, context, previousPoint));
|
|
574
887
|
}
|
|
888
|
+
return { type: "LineString", coordinates: points };
|
|
575
889
|
}
|
|
576
|
-
function
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
);
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
890
|
+
function parsePolygon3(reader, context) {
|
|
891
|
+
if (context.isEmpty) {
|
|
892
|
+
return { type: "Polygon", coordinates: [] };
|
|
893
|
+
}
|
|
894
|
+
const ringCount = reader.readVarInt();
|
|
895
|
+
const previousPoint = makePreviousPoint(context);
|
|
896
|
+
const exteriorRingLength = reader.readVarInt();
|
|
897
|
+
const exteriorRing = [];
|
|
898
|
+
for (let i = 0; i < exteriorRingLength; i++) {
|
|
899
|
+
exteriorRing.push(parseNextPoint(reader, context, previousPoint));
|
|
900
|
+
}
|
|
901
|
+
const polygon = [exteriorRing];
|
|
902
|
+
for (let i = 1; i < ringCount; i++) {
|
|
903
|
+
const interiorRingCount = reader.readVarInt();
|
|
904
|
+
const interiorRing = [];
|
|
905
|
+
for (let j = 0; j < interiorRingCount; j++) {
|
|
906
|
+
interiorRing.push(parseNextPoint(reader, context, previousPoint));
|
|
590
907
|
}
|
|
591
|
-
|
|
908
|
+
polygon.push(interiorRing);
|
|
909
|
+
}
|
|
910
|
+
return { type: "Polygon", coordinates: polygon };
|
|
911
|
+
}
|
|
912
|
+
function parseMultiPoint3(reader, context) {
|
|
913
|
+
if (context.isEmpty) {
|
|
914
|
+
return { type: "MultiPoint", coordinates: [] };
|
|
592
915
|
}
|
|
916
|
+
const previousPoint = makePreviousPoint(context);
|
|
917
|
+
const pointCount = reader.readVarInt();
|
|
593
918
|
const coordinates = [];
|
|
594
|
-
for (let i = 0; i <
|
|
595
|
-
|
|
596
|
-
const endPolygonIndex = polygonIndices[i + 1];
|
|
597
|
-
const polygonCoordinates = polygonToGeoJson(
|
|
598
|
-
data,
|
|
599
|
-
startPolygonIndex,
|
|
600
|
-
endPolygonIndex
|
|
601
|
-
).coordinates;
|
|
602
|
-
coordinates.push(polygonCoordinates);
|
|
919
|
+
for (let i = 0; i < pointCount; i++) {
|
|
920
|
+
coordinates.push(parseNextPoint(reader, context, previousPoint));
|
|
603
921
|
}
|
|
604
|
-
return { type: "
|
|
922
|
+
return { type: "MultiPoint", coordinates };
|
|
605
923
|
}
|
|
606
|
-
function
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const multi = pathIndices.length > 2;
|
|
610
|
-
if (!multi) {
|
|
611
|
-
const coordinates2 = ringToGeoJson(positions, pathIndices[0], pathIndices[1]);
|
|
612
|
-
return { type: "LineString", coordinates: coordinates2 };
|
|
924
|
+
function parseMultiLineString3(reader, context) {
|
|
925
|
+
if (context.isEmpty) {
|
|
926
|
+
return { type: "MultiLineString", coordinates: [] };
|
|
613
927
|
}
|
|
928
|
+
const previousPoint = makePreviousPoint(context);
|
|
929
|
+
const lineStringCount = reader.readVarInt();
|
|
614
930
|
const coordinates = [];
|
|
615
|
-
for (let i = 0; i <
|
|
616
|
-
const
|
|
617
|
-
|
|
931
|
+
for (let i = 0; i < lineStringCount; i++) {
|
|
932
|
+
const pointCount = reader.readVarInt();
|
|
933
|
+
const lineString = [];
|
|
934
|
+
for (let j = 0; j < pointCount; j++) {
|
|
935
|
+
lineString.push(parseNextPoint(reader, context, previousPoint));
|
|
936
|
+
}
|
|
937
|
+
coordinates.push(lineString);
|
|
618
938
|
}
|
|
619
939
|
return { type: "MultiLineString", coordinates };
|
|
620
940
|
}
|
|
621
|
-
function
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
const multi = coordinates.length > 1;
|
|
625
|
-
if (multi) {
|
|
626
|
-
return { type: "MultiPoint", coordinates };
|
|
941
|
+
function parseMultiPolygon3(reader, context) {
|
|
942
|
+
if (context.isEmpty) {
|
|
943
|
+
return { type: "MultiPolygon", coordinates: [] };
|
|
627
944
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
coord.push(Number(positions.value[k]));
|
|
945
|
+
const previousPoint = makePreviousPoint(context);
|
|
946
|
+
const polygonCount = reader.readVarInt();
|
|
947
|
+
const polygons = [];
|
|
948
|
+
for (let i = 0; i < polygonCount; i++) {
|
|
949
|
+
const ringCount = reader.readVarInt();
|
|
950
|
+
const exteriorPointCount = reader.readVarInt();
|
|
951
|
+
const exteriorRing = [];
|
|
952
|
+
for (let j = 0; j < exteriorPointCount; j++) {
|
|
953
|
+
exteriorRing.push(parseNextPoint(reader, context, previousPoint));
|
|
638
954
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
var EWKB_FLAG_SRID = 536870912;
|
|
648
|
-
var MAX_SRID = 1e4;
|
|
649
|
-
function isWKB(arrayBuffer) {
|
|
650
|
-
const dataView = new DataView(arrayBuffer);
|
|
651
|
-
let byteOffset = 0;
|
|
652
|
-
const endianness = dataView.getUint8(byteOffset);
|
|
653
|
-
byteOffset += 1;
|
|
654
|
-
if (endianness > 1) {
|
|
655
|
-
return false;
|
|
656
|
-
}
|
|
657
|
-
const littleEndian = endianness === 1;
|
|
658
|
-
const geometry = dataView.getUint32(byteOffset, littleEndian);
|
|
659
|
-
byteOffset += 4;
|
|
660
|
-
const geometryType = geometry & 7;
|
|
661
|
-
if (geometryType === 0 || geometryType > 7) {
|
|
662
|
-
return false;
|
|
663
|
-
}
|
|
664
|
-
const geometryFlags = geometry - geometryType;
|
|
665
|
-
if (geometryFlags === 0 || geometryFlags === 1e3 || geometryFlags === 2e3 || geometryFlags === 3e3) {
|
|
666
|
-
return true;
|
|
667
|
-
}
|
|
668
|
-
if ((geometryFlags & ~(EWKB_FLAG_Z | EWKB_FLAG_M | EWKB_FLAG_SRID)) !== 0) {
|
|
669
|
-
return false;
|
|
670
|
-
}
|
|
671
|
-
if (geometryFlags & EWKB_FLAG_SRID) {
|
|
672
|
-
const srid = dataView.getUint32(byteOffset, littleEndian);
|
|
673
|
-
byteOffset += 4;
|
|
674
|
-
if (srid > MAX_SRID) {
|
|
675
|
-
return false;
|
|
955
|
+
const polygon = exteriorRing ? [exteriorRing] : [];
|
|
956
|
+
for (let j = 1; j < ringCount; j++) {
|
|
957
|
+
const interiorRing = [];
|
|
958
|
+
const interiorRingLength = reader.readVarInt();
|
|
959
|
+
for (let k = 0; k < interiorRingLength; k++) {
|
|
960
|
+
interiorRing.push(parseNextPoint(reader, context, previousPoint));
|
|
961
|
+
}
|
|
962
|
+
polygon.push(interiorRing);
|
|
676
963
|
}
|
|
964
|
+
polygons.push(polygon);
|
|
677
965
|
}
|
|
678
|
-
return
|
|
966
|
+
return { type: "MultiPolygon", coordinates: polygons };
|
|
679
967
|
}
|
|
680
|
-
function
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
wkbHeader.type = "iso-wkb";
|
|
705
|
-
wkbHeader.dimensions = 3;
|
|
706
|
-
wkbHeader.coordinates = "xym";
|
|
707
|
-
break;
|
|
708
|
-
case 3:
|
|
709
|
-
wkbHeader.type = "iso-wkb";
|
|
710
|
-
wkbHeader.dimensions = 4;
|
|
711
|
-
wkbHeader.coordinates = "xyzm";
|
|
712
|
-
break;
|
|
713
|
-
default:
|
|
714
|
-
throw new Error(`WKB: Unsupported iso-wkb type: ${isoType}`);
|
|
715
|
-
}
|
|
716
|
-
const ewkbZ = geometryCode & EWKB_FLAG_Z;
|
|
717
|
-
const ewkbM = geometryCode & EWKB_FLAG_M;
|
|
718
|
-
const ewkbSRID = geometryCode & EWKB_FLAG_SRID;
|
|
719
|
-
if (ewkbZ && ewkbM) {
|
|
720
|
-
wkbHeader.type = "ewkb";
|
|
721
|
-
wkbHeader.dimensions = 4;
|
|
722
|
-
wkbHeader.coordinates = "xyzm";
|
|
723
|
-
} else if (ewkbZ) {
|
|
724
|
-
wkbHeader.type = "ewkb";
|
|
725
|
-
wkbHeader.dimensions = 3;
|
|
726
|
-
wkbHeader.coordinates = "xyz";
|
|
727
|
-
} else if (ewkbM) {
|
|
728
|
-
wkbHeader.type = "ewkb";
|
|
729
|
-
wkbHeader.dimensions = 3;
|
|
730
|
-
wkbHeader.coordinates = "xym";
|
|
968
|
+
function parseGeometryCollection2(reader, context) {
|
|
969
|
+
return { type: "GeometryCollection", geometries: [] };
|
|
970
|
+
}
|
|
971
|
+
function zigZagDecode(value) {
|
|
972
|
+
return value >> 1 ^ -(value & 1);
|
|
973
|
+
}
|
|
974
|
+
function makePointCoordinates(x, y, z, m) {
|
|
975
|
+
return z !== void 0 ? m !== void 0 ? [x, y, z, m] : [x, y, z] : [x, y];
|
|
976
|
+
}
|
|
977
|
+
function makePreviousPoint(context) {
|
|
978
|
+
return makePointCoordinates(0, 0, context.hasZ ? 0 : void 0, context.hasM ? 0 : void 0);
|
|
979
|
+
}
|
|
980
|
+
function readFirstPoint(reader, context) {
|
|
981
|
+
const x = zigZagDecode(reader.readVarInt()) / context.precisionFactor;
|
|
982
|
+
const y = zigZagDecode(reader.readVarInt()) / context.precisionFactor;
|
|
983
|
+
const z = context.hasZ ? zigZagDecode(reader.readVarInt()) / context.zPrecisionFactor : void 0;
|
|
984
|
+
const m = context.hasM ? zigZagDecode(reader.readVarInt()) / context.mPrecisionFactor : void 0;
|
|
985
|
+
return makePointCoordinates(x, y, z, m);
|
|
986
|
+
}
|
|
987
|
+
function parseNextPoint(reader, context, previousPoint) {
|
|
988
|
+
previousPoint[0] += zigZagDecode(reader.readVarInt()) / context.precisionFactor;
|
|
989
|
+
previousPoint[1] += zigZagDecode(reader.readVarInt()) / context.precisionFactor;
|
|
990
|
+
if (context.hasZ) {
|
|
991
|
+
previousPoint[2] += zigZagDecode(reader.readVarInt()) / context.zPrecisionFactor;
|
|
731
992
|
}
|
|
732
|
-
if (
|
|
733
|
-
|
|
734
|
-
wkbHeader.srid = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
|
|
735
|
-
wkbHeader.byteOffset += 4;
|
|
993
|
+
if (context.hasM) {
|
|
994
|
+
previousPoint[3] += zigZagDecode(reader.readVarInt()) / context.mPrecisionFactor;
|
|
736
995
|
}
|
|
737
|
-
return
|
|
996
|
+
return previousPoint.slice();
|
|
738
997
|
}
|
|
739
998
|
|
|
740
|
-
// src/lib/
|
|
741
|
-
function
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
case "
|
|
746
|
-
return
|
|
747
|
-
case "
|
|
748
|
-
return
|
|
749
|
-
case "
|
|
750
|
-
|
|
751
|
-
|
|
999
|
+
// ../gis/src/lib/geometry-converters/wkb/convert-geometry-to-wkt.ts
|
|
1000
|
+
function convertGeometryToWKT(geometry) {
|
|
1001
|
+
switch (geometry.type) {
|
|
1002
|
+
case "Point":
|
|
1003
|
+
return `POINT ${wrapParens(pairWKT(geometry.coordinates))}`;
|
|
1004
|
+
case "LineString":
|
|
1005
|
+
return `LINESTRING ${wrapParens(ringWKT(geometry.coordinates))}`;
|
|
1006
|
+
case "Polygon":
|
|
1007
|
+
return `POLYGON ${wrapParens(ringsWKT(geometry.coordinates))}`;
|
|
1008
|
+
case "MultiPoint":
|
|
1009
|
+
return `MULTIPOINT ${wrapParens(ringWKT(geometry.coordinates))}`;
|
|
1010
|
+
case "MultiPolygon":
|
|
1011
|
+
return `MULTIPOLYGON ${wrapParens(multiRingsWKT(geometry.coordinates))}`;
|
|
1012
|
+
case "MultiLineString":
|
|
1013
|
+
return `MULTILINESTRING ${wrapParens(ringsWKT(geometry.coordinates))}`;
|
|
1014
|
+
case "GeometryCollection":
|
|
1015
|
+
return `GEOMETRYCOLLECTION ${wrapParens(geometry.geometries.map(convertGeometryToWKT).join(", "))}`;
|
|
752
1016
|
default:
|
|
753
|
-
throw new Error(
|
|
1017
|
+
throw new Error(
|
|
1018
|
+
"convertGeometryToWKT requires a valid GeoJSON Geometry (not Feature) as input"
|
|
1019
|
+
);
|
|
754
1020
|
}
|
|
755
1021
|
}
|
|
756
|
-
function
|
|
757
|
-
|
|
758
|
-
const wkbHeader = parseWKBHeader(dataView);
|
|
759
|
-
const { geometryType, dimensions, littleEndian } = wkbHeader;
|
|
760
|
-
const offset = wkbHeader.byteOffset;
|
|
761
|
-
switch (geometryType) {
|
|
762
|
-
case 1 /* Point */:
|
|
763
|
-
const point = parsePoint2(dataView, offset, dimensions, littleEndian);
|
|
764
|
-
return point.geometry;
|
|
765
|
-
case 2 /* LineString */:
|
|
766
|
-
const line = parseLineString2(dataView, offset, dimensions, littleEndian);
|
|
767
|
-
return line.geometry;
|
|
768
|
-
case 3 /* Polygon */:
|
|
769
|
-
const polygon = parsePolygon2(dataView, offset, dimensions, littleEndian);
|
|
770
|
-
return polygon.geometry;
|
|
771
|
-
case 4 /* MultiPoint */:
|
|
772
|
-
const multiPoint = parseMultiPoint2(dataView, offset, dimensions, littleEndian);
|
|
773
|
-
multiPoint.type = "Point";
|
|
774
|
-
return multiPoint;
|
|
775
|
-
case 5 /* MultiLineString */:
|
|
776
|
-
const multiLine = parseMultiLineString2(dataView, offset, dimensions, littleEndian);
|
|
777
|
-
multiLine.type = "LineString";
|
|
778
|
-
return multiLine;
|
|
779
|
-
case 6 /* MultiPolygon */:
|
|
780
|
-
const multiPolygon = parseMultiPolygon2(dataView, offset, dimensions, littleEndian);
|
|
781
|
-
multiPolygon.type = "Polygon";
|
|
782
|
-
return multiPolygon;
|
|
783
|
-
default:
|
|
784
|
-
throw new Error(`WKB: Unsupported geometry type: ${geometryType}`);
|
|
785
|
-
}
|
|
1022
|
+
function pairWKT(c) {
|
|
1023
|
+
return c.join(" ");
|
|
786
1024
|
}
|
|
787
|
-
function
|
|
788
|
-
|
|
789
|
-
for (let i = 0; i < dimension; i++) {
|
|
790
|
-
positions[i] = dataView.getFloat64(offset, littleEndian);
|
|
791
|
-
offset += 8;
|
|
792
|
-
}
|
|
793
|
-
return {
|
|
794
|
-
geometry: { type: "Point", positions: { value: positions, size: dimension } },
|
|
795
|
-
offset
|
|
796
|
-
};
|
|
1025
|
+
function ringWKT(r) {
|
|
1026
|
+
return r.map(pairWKT).join(", ");
|
|
797
1027
|
}
|
|
798
|
-
function
|
|
799
|
-
|
|
800
|
-
offset += 4;
|
|
801
|
-
const positions = new Float64Array(nPoints * dimension);
|
|
802
|
-
for (let i = 0; i < nPoints * dimension; i++) {
|
|
803
|
-
positions[i] = dataView.getFloat64(offset, littleEndian);
|
|
804
|
-
offset += 8;
|
|
805
|
-
}
|
|
806
|
-
const pathIndices = [0];
|
|
807
|
-
if (nPoints > 0) {
|
|
808
|
-
pathIndices.push(nPoints);
|
|
809
|
-
}
|
|
810
|
-
return {
|
|
811
|
-
geometry: {
|
|
812
|
-
type: "LineString",
|
|
813
|
-
positions: { value: positions, size: dimension },
|
|
814
|
-
pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
|
|
815
|
-
},
|
|
816
|
-
offset
|
|
817
|
-
};
|
|
1028
|
+
function ringsWKT(r) {
|
|
1029
|
+
return r.map(ringWKT).map(wrapParens).join(", ");
|
|
818
1030
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
const nRings = dataView.getUint32(offset, littleEndian);
|
|
822
|
-
offset += 4;
|
|
823
|
-
const rings = [];
|
|
824
|
-
for (let i = 0; i < nRings; i++) {
|
|
825
|
-
const parsed = parseLineString2(dataView, offset, dimension, littleEndian);
|
|
826
|
-
const { positions } = parsed.geometry;
|
|
827
|
-
offset = parsed.offset;
|
|
828
|
-
rings.push(positions.value);
|
|
829
|
-
}
|
|
830
|
-
const concatenatedPositions = new Float64Array(concatTypedArrays(rings).buffer);
|
|
831
|
-
const polygonIndices = [0];
|
|
832
|
-
if (concatenatedPositions.length > 0) {
|
|
833
|
-
polygonIndices.push(concatenatedPositions.length / dimension);
|
|
834
|
-
}
|
|
835
|
-
const primitivePolygonIndices = rings.map((l) => l.length / dimension).map(cumulativeSum(0));
|
|
836
|
-
primitivePolygonIndices.unshift(0);
|
|
837
|
-
return {
|
|
838
|
-
geometry: {
|
|
839
|
-
type: "Polygon",
|
|
840
|
-
positions: { value: concatenatedPositions, size: dimension },
|
|
841
|
-
polygonIndices: {
|
|
842
|
-
value: new Uint32Array(polygonIndices),
|
|
843
|
-
size: 1
|
|
844
|
-
},
|
|
845
|
-
primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
|
|
846
|
-
},
|
|
847
|
-
offset
|
|
848
|
-
};
|
|
1031
|
+
function multiRingsWKT(r) {
|
|
1032
|
+
return r.map(ringsWKT).map(wrapParens).join(", ");
|
|
849
1033
|
}
|
|
850
|
-
function
|
|
851
|
-
|
|
852
|
-
offset += 4;
|
|
853
|
-
const binaryPointGeometries = [];
|
|
854
|
-
for (let i = 0; i < nPoints; i++) {
|
|
855
|
-
const littleEndianPoint = dataView.getUint8(offset) === 1;
|
|
856
|
-
offset++;
|
|
857
|
-
if (dataView.getUint32(offset, littleEndianPoint) % 1e3 !== 1) {
|
|
858
|
-
throw new Error("WKB: Inner geometries of MultiPoint not of type Point");
|
|
859
|
-
}
|
|
860
|
-
offset += 4;
|
|
861
|
-
const parsed = parsePoint2(dataView, offset, dimension, littleEndianPoint);
|
|
862
|
-
offset = parsed.offset;
|
|
863
|
-
binaryPointGeometries.push(parsed.geometry);
|
|
864
|
-
}
|
|
865
|
-
return concatenateBinaryPointGeometries(binaryPointGeometries, dimension);
|
|
866
|
-
}
|
|
867
|
-
function parseMultiLineString2(dataView, offset, dimension, littleEndian) {
|
|
868
|
-
const nLines = dataView.getUint32(offset, littleEndian);
|
|
869
|
-
offset += 4;
|
|
870
|
-
const binaryLineGeometries = [];
|
|
871
|
-
for (let i = 0; i < nLines; i++) {
|
|
872
|
-
const littleEndianLine = dataView.getUint8(offset) === 1;
|
|
873
|
-
offset++;
|
|
874
|
-
if (dataView.getUint32(offset, littleEndianLine) % 1e3 !== 2) {
|
|
875
|
-
throw new Error("WKB: Inner geometries of MultiLineString not of type LineString");
|
|
876
|
-
}
|
|
877
|
-
offset += 4;
|
|
878
|
-
const parsed = parseLineString2(dataView, offset, dimension, littleEndianLine);
|
|
879
|
-
offset = parsed.offset;
|
|
880
|
-
binaryLineGeometries.push(parsed.geometry);
|
|
881
|
-
}
|
|
882
|
-
return concatenateBinaryLineGeometries(binaryLineGeometries, dimension);
|
|
883
|
-
}
|
|
884
|
-
function parseMultiPolygon2(dataView, offset, dimension, littleEndian) {
|
|
885
|
-
const nPolygons = dataView.getUint32(offset, littleEndian);
|
|
886
|
-
offset += 4;
|
|
887
|
-
const binaryPolygonGeometries = [];
|
|
888
|
-
for (let i = 0; i < nPolygons; i++) {
|
|
889
|
-
const littleEndianPolygon = dataView.getUint8(offset) === 1;
|
|
890
|
-
offset++;
|
|
891
|
-
if (dataView.getUint32(offset, littleEndianPolygon) % 1e3 !== 3) {
|
|
892
|
-
throw new Error("WKB: Inner geometries of MultiPolygon not of type Polygon");
|
|
893
|
-
}
|
|
894
|
-
offset += 4;
|
|
895
|
-
const parsed = parsePolygon2(dataView, offset, dimension, littleEndianPolygon);
|
|
896
|
-
offset = parsed.offset;
|
|
897
|
-
binaryPolygonGeometries.push(parsed.geometry);
|
|
898
|
-
}
|
|
899
|
-
return concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension);
|
|
900
|
-
}
|
|
901
|
-
function concatenateBinaryPointGeometries(binaryPointGeometries, dimension) {
|
|
902
|
-
const positions = binaryPointGeometries.map((geometry) => geometry.positions.value);
|
|
903
|
-
const concatenatedPositions = new Float64Array(concatTypedArrays(positions).buffer);
|
|
904
|
-
return {
|
|
905
|
-
type: "Point",
|
|
906
|
-
positions: { value: concatenatedPositions, size: dimension }
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
function concatenateBinaryLineGeometries(binaryLineGeometries, dimension) {
|
|
910
|
-
const lines = binaryLineGeometries.map((geometry) => geometry.positions.value);
|
|
911
|
-
const concatenatedPositions = new Float64Array(concatTypedArrays(lines).buffer);
|
|
912
|
-
const pathIndices = lines.map((line) => line.length / dimension).map(cumulativeSum(0));
|
|
913
|
-
pathIndices.unshift(0);
|
|
914
|
-
return {
|
|
915
|
-
type: "LineString",
|
|
916
|
-
positions: { value: concatenatedPositions, size: dimension },
|
|
917
|
-
pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
function concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension) {
|
|
921
|
-
const polygons = [];
|
|
922
|
-
const primitivePolygons = [];
|
|
923
|
-
for (const binaryPolygon of binaryPolygonGeometries) {
|
|
924
|
-
const { positions, primitivePolygonIndices: primitivePolygonIndices2 } = binaryPolygon;
|
|
925
|
-
polygons.push(positions.value);
|
|
926
|
-
primitivePolygons.push(primitivePolygonIndices2.value);
|
|
927
|
-
}
|
|
928
|
-
const concatenatedPositions = new Float64Array(concatTypedArrays(polygons).buffer);
|
|
929
|
-
const polygonIndices = polygons.map((p) => p.length / dimension).map(cumulativeSum(0));
|
|
930
|
-
polygonIndices.unshift(0);
|
|
931
|
-
const primitivePolygonIndices = [0];
|
|
932
|
-
for (const primitivePolygon of primitivePolygons) {
|
|
933
|
-
primitivePolygonIndices.push(
|
|
934
|
-
...primitivePolygon.filter((x) => x > 0).map((x) => x + primitivePolygonIndices[primitivePolygonIndices.length - 1])
|
|
935
|
-
);
|
|
936
|
-
}
|
|
937
|
-
return {
|
|
938
|
-
type: "Polygon",
|
|
939
|
-
positions: { value: concatenatedPositions, size: dimension },
|
|
940
|
-
polygonIndices: { value: new Uint32Array(polygonIndices), size: 1 },
|
|
941
|
-
primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
|
|
942
|
-
};
|
|
943
|
-
}
|
|
944
|
-
function concatTypedArrays(arrays) {
|
|
945
|
-
let byteLength = 0;
|
|
946
|
-
for (let i = 0; i < arrays.length; ++i) {
|
|
947
|
-
byteLength += arrays[i].byteLength;
|
|
948
|
-
}
|
|
949
|
-
const buffer = new Uint8Array(byteLength);
|
|
950
|
-
let byteOffset = 0;
|
|
951
|
-
for (let i = 0; i < arrays.length; ++i) {
|
|
952
|
-
const data = new Uint8Array(arrays[i].buffer);
|
|
953
|
-
byteLength = data.length;
|
|
954
|
-
for (let j = 0; j < byteLength; ++j) {
|
|
955
|
-
buffer[byteOffset++] = data[j];
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
return buffer;
|
|
1034
|
+
function wrapParens(s) {
|
|
1035
|
+
return `(${s})`;
|
|
959
1036
|
}
|
|
960
1037
|
|
|
961
|
-
// src/
|
|
962
|
-
var WKBWorkerLoader = {
|
|
963
|
-
dataType: null,
|
|
964
|
-
batchType: null,
|
|
965
|
-
name: "WKB",
|
|
966
|
-
id: "wkb",
|
|
967
|
-
module: "wkt",
|
|
968
|
-
version: VERSION,
|
|
969
|
-
worker: true,
|
|
970
|
-
category: "geometry",
|
|
971
|
-
extensions: ["wkb"],
|
|
972
|
-
mimeTypes: [],
|
|
973
|
-
// TODO can we define static, serializable tests, eg. some binary strings?
|
|
974
|
-
tests: [isWKB],
|
|
975
|
-
options: {
|
|
976
|
-
wkb: {
|
|
977
|
-
shape: "binary-geometry"
|
|
978
|
-
// 'geojson-geometry'
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
};
|
|
982
|
-
var WKBLoader = {
|
|
983
|
-
...WKBWorkerLoader,
|
|
984
|
-
parse: async (arrayBuffer) => parseWKB(arrayBuffer),
|
|
985
|
-
parseSync: parseWKB
|
|
986
|
-
};
|
|
987
|
-
|
|
988
|
-
// src/lib/utils/binary-writer.ts
|
|
1038
|
+
// ../gis/src/lib/utils/binary-writer.ts
|
|
989
1039
|
var LE = true;
|
|
990
1040
|
var BE = false;
|
|
991
1041
|
var BinaryWriter = class {
|
|
@@ -1080,6 +1130,12 @@ var __exports__ = (() => {
|
|
|
1080
1130
|
this.writeUInt8(value & 127);
|
|
1081
1131
|
return length;
|
|
1082
1132
|
}
|
|
1133
|
+
writeTypedArray(typedArray) {
|
|
1134
|
+
this._ensureSize(typedArray.byteLength);
|
|
1135
|
+
const tempArray = new Uint8Array(this.arrayBuffer);
|
|
1136
|
+
tempArray.set(typedArray, this.byteOffset);
|
|
1137
|
+
this.byteOffset += typedArray.byteLength;
|
|
1138
|
+
}
|
|
1083
1139
|
/** Append another ArrayBuffer to this ArrayBuffer */
|
|
1084
1140
|
writeBuffer(arrayBuffer) {
|
|
1085
1141
|
this._ensureSize(arrayBuffer.byteLength);
|
|
@@ -1102,8 +1158,8 @@ var __exports__ = (() => {
|
|
|
1102
1158
|
}
|
|
1103
1159
|
};
|
|
1104
1160
|
|
|
1105
|
-
// src/lib/
|
|
1106
|
-
function
|
|
1161
|
+
// ../gis/src/lib/geometry-converters/wkb/convert-geometry-to-wkb.ts
|
|
1162
|
+
function convertGeometryToWKB(geometry, options = {}) {
|
|
1107
1163
|
if (geometry.type === "Feature") {
|
|
1108
1164
|
geometry = geometry.geometry;
|
|
1109
1165
|
}
|
|
@@ -1199,7 +1255,7 @@ var __exports__ = (() => {
|
|
|
1199
1255
|
const writer = new BinaryWriter(getPolygonSize(coordinates, options));
|
|
1200
1256
|
writer.writeInt8(1);
|
|
1201
1257
|
writeWkbType(writer, 3 /* Polygon */, options);
|
|
1202
|
-
const [exteriorRing, ...interiorRings] = coordinates;
|
|
1258
|
+
const [exteriorRing = [], ...interiorRings] = coordinates;
|
|
1203
1259
|
if (exteriorRing.length > 0) {
|
|
1204
1260
|
writer.writeUInt32LE(1 + interiorRings.length);
|
|
1205
1261
|
writer.writeUInt32LE(exteriorRing.length);
|
|
@@ -1219,7 +1275,7 @@ var __exports__ = (() => {
|
|
|
1219
1275
|
}
|
|
1220
1276
|
function getPolygonSize(coordinates, options) {
|
|
1221
1277
|
const coordinateSize = getCoordinateSize(options);
|
|
1222
|
-
const [exteriorRing, ...interiorRings] = coordinates;
|
|
1278
|
+
const [exteriorRing = [], ...interiorRings] = coordinates;
|
|
1223
1279
|
let size = 1 + 4 + 4;
|
|
1224
1280
|
if (exteriorRing.length > 0) {
|
|
1225
1281
|
size += 4 + exteriorRing.length * coordinateSize;
|
|
@@ -1293,7 +1349,7 @@ var __exports__ = (() => {
|
|
|
1293
1349
|
writeWkbType(writer, 7 /* GeometryCollection */, options);
|
|
1294
1350
|
writer.writeUInt32LE(collection.geometries.length);
|
|
1295
1351
|
for (const geometry of collection.geometries) {
|
|
1296
|
-
const arrayBuffer =
|
|
1352
|
+
const arrayBuffer = convertGeometryToWKB(geometry, options);
|
|
1297
1353
|
writer.writeBuffer(arrayBuffer);
|
|
1298
1354
|
}
|
|
1299
1355
|
return writer.arrayBuffer;
|
|
@@ -1337,379 +1393,512 @@ var __exports__ = (() => {
|
|
|
1337
1393
|
return coordinateSize;
|
|
1338
1394
|
}
|
|
1339
1395
|
|
|
1340
|
-
// src/wkb-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1396
|
+
// ../gis/src/lib/geometry-converters/wkb/convert-geometry-to-twkb.ts
|
|
1397
|
+
function convertGeometryToTWKB(geometry, options) {
|
|
1398
|
+
const writer = new BinaryWriter(0, true);
|
|
1399
|
+
const context = {
|
|
1400
|
+
...getTwkbPrecision(5, 0, 0),
|
|
1401
|
+
hasZ: options?.hasZ,
|
|
1402
|
+
hasM: options?.hasM
|
|
1403
|
+
};
|
|
1404
|
+
encodeGeometry(writer, geometry, context);
|
|
1405
|
+
return writer.arrayBuffer;
|
|
1406
|
+
}
|
|
1407
|
+
function encodeGeometry(writer, geometry, context) {
|
|
1408
|
+
switch (geometry.type) {
|
|
1409
|
+
case "Point":
|
|
1410
|
+
return encodePoint2(writer, context, geometry);
|
|
1411
|
+
case "LineString":
|
|
1412
|
+
return encodeLineString2(writer, context, geometry);
|
|
1413
|
+
case "Polygon":
|
|
1414
|
+
return encodePolygon2(writer, context, geometry);
|
|
1415
|
+
case "MultiPoint":
|
|
1416
|
+
return encodeMultiPoint2(writer, context, geometry);
|
|
1417
|
+
case "MultiLineString":
|
|
1418
|
+
return encodeMultiLineString2(writer, context, geometry);
|
|
1419
|
+
case "MultiPolygon":
|
|
1420
|
+
return encodeMultiPolygon2(writer, context, geometry);
|
|
1421
|
+
case "GeometryCollection":
|
|
1422
|
+
return encodeGeometryCollection2(writer, context, geometry);
|
|
1423
|
+
default:
|
|
1424
|
+
throw new Error("unsupported geometry type");
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
function encodePoint2(writer, context, point) {
|
|
1428
|
+
const isEmpty = point.coordinates.length === 0 || point[0] === "undefined" || point[1] === "undefined";
|
|
1429
|
+
writeTwkbHeader(writer, context, 1 /* Point */, isEmpty);
|
|
1430
|
+
if (!isEmpty) {
|
|
1431
|
+
const previousPoint = [0, 0, 0, 0];
|
|
1432
|
+
writeTwkbPoint(writer, context, point.coordinates, previousPoint);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
function encodeLineString2(writer, context, lineString) {
|
|
1436
|
+
const points = lineString.coordinates;
|
|
1437
|
+
const isEmpty = points.length === 0;
|
|
1438
|
+
writeTwkbHeader(writer, context, 2 /* LineString */, isEmpty);
|
|
1439
|
+
if (!isEmpty) {
|
|
1440
|
+
writer.writeVarInt(points.length);
|
|
1441
|
+
const previousPoint = [0, 0, 0, 0];
|
|
1442
|
+
for (const point of points) {
|
|
1443
|
+
writeTwkbPoint(writer, context, point, previousPoint);
|
|
1351
1444
|
}
|
|
1352
|
-
},
|
|
1353
|
-
async encode(data, options) {
|
|
1354
|
-
return encodeWKB(data, options?.wkb);
|
|
1355
|
-
},
|
|
1356
|
-
encodeSync(data, options) {
|
|
1357
|
-
return encodeWKB(data, options?.wkb);
|
|
1358
1445
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1446
|
+
return writer.arrayBuffer;
|
|
1447
|
+
}
|
|
1448
|
+
function encodePolygon2(writer, context, polygon) {
|
|
1449
|
+
const polygonRings = polygon.coordinates;
|
|
1450
|
+
const isEmpty = polygonRings.length === 0;
|
|
1451
|
+
writeTwkbHeader(writer, context, 3 /* Polygon */, isEmpty);
|
|
1452
|
+
if (!isEmpty) {
|
|
1453
|
+
writer.writeVarInt(polygonRings.length);
|
|
1454
|
+
const previousPoint = [0, 0, 0, 0];
|
|
1455
|
+
for (const ring of polygonRings) {
|
|
1456
|
+
writer.writeVarInt(ring.length);
|
|
1457
|
+
for (const point of ring) {
|
|
1458
|
+
writeTwkbPoint(writer, context, previousPoint, point);
|
|
1459
|
+
}
|
|
1372
1460
|
}
|
|
1373
1461
|
}
|
|
1462
|
+
return writer.arrayBuffer;
|
|
1374
1463
|
}
|
|
1375
|
-
function
|
|
1376
|
-
const
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1464
|
+
function encodeMultiPoint2(writer, context, multiPoint) {
|
|
1465
|
+
const points = multiPoint.coordinates;
|
|
1466
|
+
const isEmpty = points.length === 0;
|
|
1467
|
+
writeTwkbHeader(writer, context, 4 /* MultiPoint */, isEmpty);
|
|
1468
|
+
if (!isEmpty) {
|
|
1469
|
+
writer.writeVarInt(points.length);
|
|
1470
|
+
const previousPoint = [0, 0, 0, 0];
|
|
1471
|
+
for (let i = 0; i < points.length; i++) {
|
|
1472
|
+
writeTwkbPoint(writer, context, previousPoint, points[i]);
|
|
1473
|
+
}
|
|
1381
1474
|
}
|
|
1382
|
-
return string;
|
|
1383
1475
|
}
|
|
1384
|
-
function
|
|
1385
|
-
const
|
|
1386
|
-
const
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1476
|
+
function encodeMultiLineString2(writer, context, multiLineStrings) {
|
|
1477
|
+
const lineStrings = multiLineStrings.coordinates;
|
|
1478
|
+
const isEmpty = lineStrings.length === 0;
|
|
1479
|
+
writeTwkbHeader(writer, context, 5 /* MultiLineString */, isEmpty);
|
|
1480
|
+
if (!isEmpty) {
|
|
1481
|
+
writer.writeVarInt(lineStrings.length);
|
|
1482
|
+
const previousPoint = [0, 0, 0, 0];
|
|
1483
|
+
for (const lineString of lineStrings) {
|
|
1484
|
+
writer.writeVarInt(lineString.length);
|
|
1485
|
+
for (const point of lineString) {
|
|
1486
|
+
writeTwkbPoint(writer, context, previousPoint, point);
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1392
1489
|
}
|
|
1393
|
-
return
|
|
1490
|
+
return writer.arrayBuffer;
|
|
1394
1491
|
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
parse: async (arrayBuffer) => parseHexWKB(new TextDecoder().decode(arrayBuffer)),
|
|
1413
|
-
parseTextSync: parseHexWKB
|
|
1414
|
-
};
|
|
1415
|
-
function parseHexWKB(text, options) {
|
|
1416
|
-
const uint8Array = decodeHex(text);
|
|
1417
|
-
const binaryGeometry = WKBLoader.parseSync?.(uint8Array.buffer, options);
|
|
1418
|
-
return binaryGeometry;
|
|
1419
|
-
}
|
|
1420
|
-
function isHexWKB(string) {
|
|
1421
|
-
if (!string) {
|
|
1422
|
-
return false;
|
|
1423
|
-
}
|
|
1424
|
-
if (string.length < 10 || string.length % 2 !== 0) {
|
|
1425
|
-
return false;
|
|
1492
|
+
function encodeMultiPolygon2(writer, context, multiPolygon) {
|
|
1493
|
+
const { coordinates } = multiPolygon;
|
|
1494
|
+
const isEmpty = coordinates.length === 0;
|
|
1495
|
+
writeTwkbHeader(writer, context, 6 /* MultiPolygon */, isEmpty);
|
|
1496
|
+
if (!isEmpty) {
|
|
1497
|
+
const polygons = coordinates;
|
|
1498
|
+
writer.writeVarInt(polygons.length);
|
|
1499
|
+
const previousPoint = [0, 0, 0, 0];
|
|
1500
|
+
for (const polygonRings of polygons) {
|
|
1501
|
+
writer.writeVarInt(polygonRings.length);
|
|
1502
|
+
for (const ring of polygonRings) {
|
|
1503
|
+
writer.writeVarInt(ring.length);
|
|
1504
|
+
for (const point of ring) {
|
|
1505
|
+
writeTwkbPoint(writer, context, previousPoint, point);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1426
1509
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1510
|
+
}
|
|
1511
|
+
function encodeGeometryCollection2(writer, context, geometryCollection) {
|
|
1512
|
+
const { geometries } = geometryCollection;
|
|
1513
|
+
const isEmpty = geometries.length === 0;
|
|
1514
|
+
writeTwkbHeader(writer, context, 7 /* GeometryCollection */, isEmpty);
|
|
1515
|
+
if (geometries.length > 0) {
|
|
1516
|
+
writer.writeVarInt(geometries.length);
|
|
1517
|
+
for (const geometry of geometries) {
|
|
1518
|
+
encodeGeometry(writer, geometry, context);
|
|
1519
|
+
}
|
|
1429
1520
|
}
|
|
1430
|
-
return /^[0-9a-fA-F]+$/.test(string.slice(2));
|
|
1431
1521
|
}
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1522
|
+
function writeTwkbHeader(writer, context, geometryType, isEmpty) {
|
|
1523
|
+
const type = (zigZagEncode(context.xy) << 4) + geometryType;
|
|
1524
|
+
let metadataHeader = context.hasZ || context.hasM ? 1 << 3 : 0;
|
|
1525
|
+
metadataHeader += isEmpty ? 1 << 4 : 0;
|
|
1526
|
+
writer.writeUInt8(type);
|
|
1527
|
+
writer.writeUInt8(metadataHeader);
|
|
1528
|
+
if (context.hasZ || context.hasM) {
|
|
1529
|
+
let extendedPrecision = 0;
|
|
1530
|
+
if (context.hasZ) {
|
|
1531
|
+
extendedPrecision |= 1;
|
|
1532
|
+
}
|
|
1533
|
+
if (context.hasM) {
|
|
1534
|
+
extendedPrecision |= 2;
|
|
1535
|
+
}
|
|
1536
|
+
writer.writeUInt8(extendedPrecision);
|
|
1444
1537
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1538
|
+
}
|
|
1539
|
+
function writeTwkbPoint(writer, context, point, previousPoint) {
|
|
1540
|
+
const x = point[0] * context.xyFactor;
|
|
1541
|
+
const y = point[1] * context.xyFactor;
|
|
1542
|
+
const z = point[2] * context.zFactor;
|
|
1543
|
+
const m = point[3] * context.mFactor;
|
|
1544
|
+
writer.writeVarInt(zigZagEncode(x - previousPoint[0]));
|
|
1545
|
+
writer.writeVarInt(zigZagEncode(y - previousPoint[1]));
|
|
1546
|
+
if (context.hasZ) {
|
|
1547
|
+
writer.writeVarInt(zigZagEncode(z - previousPoint[2]));
|
|
1449
1548
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
this.byteOffset += 2;
|
|
1453
|
-
return value;
|
|
1549
|
+
if (context.hasM) {
|
|
1550
|
+
writer.writeVarInt(zigZagEncode(m - previousPoint[3]));
|
|
1454
1551
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1552
|
+
previousPoint[0] = x;
|
|
1553
|
+
previousPoint[1] = y;
|
|
1554
|
+
previousPoint[2] = z;
|
|
1555
|
+
previousPoint[3] = m;
|
|
1556
|
+
}
|
|
1557
|
+
function zigZagEncode(value) {
|
|
1558
|
+
return value << 1 ^ value >> 31;
|
|
1559
|
+
}
|
|
1560
|
+
function getTwkbPrecision(xyPrecision, zPrecision, mPrecision) {
|
|
1561
|
+
return {
|
|
1562
|
+
xy: xyPrecision,
|
|
1563
|
+
z: zPrecision,
|
|
1564
|
+
m: mPrecision,
|
|
1565
|
+
xyFactor: Math.pow(10, xyPrecision),
|
|
1566
|
+
zFactor: Math.pow(10, zPrecision),
|
|
1567
|
+
mFactor: Math.pow(10, mPrecision)
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
// ../gis/src/lib/wkt-crs/parse-wkt-crs.ts
|
|
1572
|
+
function parseWKTCRS(wkt, options) {
|
|
1573
|
+
if (options?.debug) {
|
|
1574
|
+
console.log("[wktcrs] parse starting with\n", wkt);
|
|
1459
1575
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
return
|
|
1576
|
+
wkt = wkt.replace(/[A-Z][A-Z\d_]+\[/gi, (match) => `["${match.substr(0, match.length - 1)}",`);
|
|
1577
|
+
wkt = wkt.replace(/, ?([A-Z][A-Z\d_]+[,\]])/gi, (match, p1) => {
|
|
1578
|
+
const varname = p1.substr(0, p1.length - 1);
|
|
1579
|
+
return `,"${options?.raw ? "raw:" : ""}${varname}"${p1[p1.length - 1]}`;
|
|
1580
|
+
});
|
|
1581
|
+
if (options?.raw) {
|
|
1582
|
+
wkt = wkt.replace(/, {0,2}(-?[\.\d]+)(?=,|\])/g, function(match, p1) {
|
|
1583
|
+
return `,"${options?.raw ? "raw:" : ""}${p1}"`;
|
|
1584
|
+
});
|
|
1464
1585
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
this.byteOffset += 2;
|
|
1468
|
-
return value;
|
|
1586
|
+
if (options?.debug) {
|
|
1587
|
+
console.log(`[wktcrs] json'd wkt: '${wkt}'`);
|
|
1469
1588
|
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1589
|
+
let data;
|
|
1590
|
+
try {
|
|
1591
|
+
data = JSON.parse(wkt);
|
|
1592
|
+
} catch (error) {
|
|
1593
|
+
console.error(`[wktcrs] failed to parse '${wkt}'`);
|
|
1594
|
+
throw error;
|
|
1474
1595
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
this.byteOffset += 4;
|
|
1478
|
-
return value;
|
|
1596
|
+
if (options?.debug) {
|
|
1597
|
+
console.log(`[wktcrs] json parsed: '${wkt}'`);
|
|
1479
1598
|
}
|
|
1480
|
-
|
|
1481
|
-
const
|
|
1482
|
-
|
|
1483
|
-
|
|
1599
|
+
function process(data2, parent) {
|
|
1600
|
+
const kw = data2[0];
|
|
1601
|
+
data2.forEach(function(it) {
|
|
1602
|
+
if (Array.isArray(it)) {
|
|
1603
|
+
process(it, data2);
|
|
1604
|
+
}
|
|
1605
|
+
});
|
|
1606
|
+
const kwarr = `MULTIPLE_${kw}`;
|
|
1607
|
+
if (kwarr in parent) {
|
|
1608
|
+
parent[kwarr].push(data2);
|
|
1609
|
+
} else if (kw in parent) {
|
|
1610
|
+
parent[kwarr] = [parent[kw], data2];
|
|
1611
|
+
delete parent[kw];
|
|
1612
|
+
} else {
|
|
1613
|
+
parent[kw] = data2;
|
|
1614
|
+
}
|
|
1615
|
+
return parent;
|
|
1484
1616
|
}
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
let nextByte;
|
|
1489
|
-
do {
|
|
1490
|
-
nextByte = this.dataView.getUint8(this.byteOffset + bytesRead);
|
|
1491
|
-
result += (nextByte & 127) << 7 * bytesRead;
|
|
1492
|
-
bytesRead++;
|
|
1493
|
-
} while (nextByte >= 128);
|
|
1494
|
-
this.byteOffset += bytesRead;
|
|
1495
|
-
return result;
|
|
1617
|
+
const result = process(data, [data]);
|
|
1618
|
+
if (options?.debug) {
|
|
1619
|
+
console.log("[wktcrs] parse returning", result);
|
|
1496
1620
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
// src/lib/parse-twkb.ts
|
|
1500
|
-
function isTWKB(arrayBuffer) {
|
|
1501
|
-
const binaryReader = new BinaryReader(arrayBuffer);
|
|
1502
|
-
const type = binaryReader.readUInt8();
|
|
1503
|
-
const geometryType = type & 15;
|
|
1504
|
-
if (geometryType < 1 || geometryType > 7) {
|
|
1505
|
-
return false;
|
|
1621
|
+
if (options?.sort) {
|
|
1622
|
+
sort(result, options);
|
|
1506
1623
|
}
|
|
1507
|
-
return
|
|
1624
|
+
return result;
|
|
1508
1625
|
}
|
|
1509
|
-
function
|
|
1510
|
-
const
|
|
1511
|
-
const
|
|
1512
|
-
if (
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1626
|
+
function sort(data, options) {
|
|
1627
|
+
const keys = Object.keys(data).filter((k) => !/\d+/.test(k));
|
|
1628
|
+
const keywords = options?.keywords || [];
|
|
1629
|
+
if (!options?.keywords) {
|
|
1630
|
+
const counts = {};
|
|
1631
|
+
if (Array.isArray(data)) {
|
|
1632
|
+
data.forEach((it) => {
|
|
1633
|
+
if (Array.isArray(it) && it.length >= 2 && typeof it[1] === "string") {
|
|
1634
|
+
const k = it[0];
|
|
1635
|
+
if (!counts[k])
|
|
1636
|
+
counts[k] = 0;
|
|
1637
|
+
counts[k]++;
|
|
1638
|
+
}
|
|
1639
|
+
});
|
|
1640
|
+
for (const k in counts) {
|
|
1641
|
+
if (counts[k] > 0)
|
|
1642
|
+
keywords.push(k);
|
|
1643
|
+
}
|
|
1526
1644
|
}
|
|
1527
1645
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
}
|
|
1551
|
-
return {
|
|
1552
|
-
geometryType,
|
|
1553
|
-
precision,
|
|
1554
|
-
precisionFactor: Math.pow(10, precision),
|
|
1555
|
-
hasBoundingBox: Boolean(metadataHeader >> 0 & 1),
|
|
1556
|
-
hasSizeAttribute: Boolean(metadataHeader >> 1 & 1),
|
|
1557
|
-
hasIdList: Boolean(metadataHeader >> 2 & 1),
|
|
1558
|
-
hasExtendedPrecision,
|
|
1559
|
-
isEmpty: Boolean(metadataHeader >> 4 & 1),
|
|
1560
|
-
hasZ,
|
|
1561
|
-
hasM,
|
|
1562
|
-
zPrecision,
|
|
1563
|
-
zPrecisionFactor,
|
|
1564
|
-
mPrecision,
|
|
1565
|
-
mPrecisionFactor
|
|
1566
|
-
};
|
|
1646
|
+
keys.forEach((key) => {
|
|
1647
|
+
data[key] = sort(data[key]);
|
|
1648
|
+
});
|
|
1649
|
+
keywords.forEach((key) => {
|
|
1650
|
+
const indices = [];
|
|
1651
|
+
const params = [];
|
|
1652
|
+
data.forEach((item, i) => {
|
|
1653
|
+
if (Array.isArray(item) && item[0] === key) {
|
|
1654
|
+
indices.push(i);
|
|
1655
|
+
params.push(item);
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
params.sort((a, b) => {
|
|
1659
|
+
a = a[1].toString();
|
|
1660
|
+
b = b[1].toString();
|
|
1661
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
1662
|
+
});
|
|
1663
|
+
params.forEach((param, i) => {
|
|
1664
|
+
data[indices[i]] = param;
|
|
1665
|
+
});
|
|
1666
|
+
});
|
|
1667
|
+
return data;
|
|
1567
1668
|
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
return parseLineString3(binaryReader, context);
|
|
1574
|
-
case 3 /* Polygon */:
|
|
1575
|
-
return parsePolygon3(binaryReader, context);
|
|
1576
|
-
case 4 /* MultiPoint */:
|
|
1577
|
-
return parseMultiPoint3(binaryReader, context);
|
|
1578
|
-
case 5 /* MultiLineString */:
|
|
1579
|
-
return parseMultiLineString3(binaryReader, context);
|
|
1580
|
-
case 6 /* MultiPolygon */:
|
|
1581
|
-
return parseMultiPolygon3(binaryReader, context);
|
|
1582
|
-
case 7 /* GeometryCollection */:
|
|
1583
|
-
return parseGeometryCollection2(binaryReader, context);
|
|
1584
|
-
default:
|
|
1585
|
-
throw new Error(`GeometryType ${geometryType} not supported`);
|
|
1669
|
+
|
|
1670
|
+
// ../gis/src/lib/wkt-crs/encode-wkt-crs.ts
|
|
1671
|
+
function encodeWKTCRS(wkt, options) {
|
|
1672
|
+
if (Array.isArray(wkt) && wkt.length === 1 && Array.isArray(wkt[0])) {
|
|
1673
|
+
wkt = wkt[0];
|
|
1586
1674
|
}
|
|
1675
|
+
const [kw, ...attrs] = wkt;
|
|
1676
|
+
const str = `${kw}[${attrs.map((attr) => {
|
|
1677
|
+
if (Array.isArray(attr)) {
|
|
1678
|
+
return encodeWKTCRS(attr, options);
|
|
1679
|
+
} else if (typeof attr === "number") {
|
|
1680
|
+
return attr.toString();
|
|
1681
|
+
} else if (typeof attr === "string") {
|
|
1682
|
+
if (attr.startsWith("raw:")) {
|
|
1683
|
+
return attr.replace("raw:", "");
|
|
1684
|
+
}
|
|
1685
|
+
return `"${attr}"`;
|
|
1686
|
+
}
|
|
1687
|
+
throw new Error(`[wktcrs] unexpected attribute "${attr}"`);
|
|
1688
|
+
}).join(",")}]`;
|
|
1689
|
+
return str;
|
|
1587
1690
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1691
|
+
|
|
1692
|
+
// ../gis/src/lib/utils/hex-transcoder.ts
|
|
1693
|
+
var alphabet = "0123456789abcdef";
|
|
1694
|
+
var encodeLookup = [];
|
|
1695
|
+
var decodeLookup = [];
|
|
1696
|
+
for (let i = 0; i < 256; i++) {
|
|
1697
|
+
encodeLookup[i] = alphabet[i >> 4 & 15] + alphabet[i & 15];
|
|
1698
|
+
if (i < 16) {
|
|
1699
|
+
if (i < 10) {
|
|
1700
|
+
decodeLookup[48 + i] = i;
|
|
1701
|
+
} else {
|
|
1702
|
+
decodeLookup[97 - 10 + i] = i;
|
|
1703
|
+
}
|
|
1591
1704
|
}
|
|
1592
|
-
return { type: "Point", coordinates: readFirstPoint(reader, context) };
|
|
1593
1705
|
}
|
|
1594
|
-
function
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
points.push(parseNextPoint(reader, context, previousPoint));
|
|
1706
|
+
function decodeHex(string) {
|
|
1707
|
+
const sizeof = string.length >> 1;
|
|
1708
|
+
const length = sizeof << 1;
|
|
1709
|
+
const array = new Uint8Array(sizeof);
|
|
1710
|
+
let n = 0;
|
|
1711
|
+
let i = 0;
|
|
1712
|
+
while (i < length) {
|
|
1713
|
+
array[n++] = decodeLookup[string.charCodeAt(i++)] << 4 | decodeLookup[string.charCodeAt(i++)];
|
|
1603
1714
|
}
|
|
1604
|
-
return
|
|
1715
|
+
return array;
|
|
1605
1716
|
}
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1717
|
+
|
|
1718
|
+
// src/lib/version.ts
|
|
1719
|
+
var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
|
|
1720
|
+
|
|
1721
|
+
// src/wkt-crs-loader.ts
|
|
1722
|
+
var WKTCRSLoader = {
|
|
1723
|
+
dataType: null,
|
|
1724
|
+
batchType: null,
|
|
1725
|
+
name: "WKT CRS (Well-Known Text Coordinate Reference System)",
|
|
1726
|
+
id: "wkt-crs",
|
|
1727
|
+
module: "wkt-crs",
|
|
1728
|
+
version: VERSION,
|
|
1729
|
+
worker: true,
|
|
1730
|
+
extensions: [],
|
|
1731
|
+
mimeTypes: ["text/plain"],
|
|
1732
|
+
category: "json",
|
|
1733
|
+
text: true,
|
|
1734
|
+
options: {
|
|
1735
|
+
"wkt-crs": {}
|
|
1736
|
+
},
|
|
1737
|
+
parse: async (arrayBuffer, options) => parseWKTCRS(new TextDecoder().decode(arrayBuffer), options?.["wkt-crs"]),
|
|
1738
|
+
parseTextSync: (string, options) => parseWKTCRS(string, options?.["wkt-crs"])
|
|
1739
|
+
};
|
|
1740
|
+
|
|
1741
|
+
// src/wkt-crs-writer.ts
|
|
1742
|
+
var WKTCRSWriter = {
|
|
1743
|
+
name: "WKT CRS (Well-Known Text Coordinate Reference System)",
|
|
1744
|
+
id: "wkt-crs",
|
|
1745
|
+
module: "wkt-crs",
|
|
1746
|
+
version: VERSION,
|
|
1747
|
+
worker: true,
|
|
1748
|
+
extensions: [],
|
|
1749
|
+
mimeTypes: ["text/plain"],
|
|
1750
|
+
// category: 'json',
|
|
1751
|
+
text: true,
|
|
1752
|
+
options: {
|
|
1753
|
+
"wkt-crs": {}
|
|
1754
|
+
},
|
|
1755
|
+
encode: async (wktcrs, options) => new TextEncoder().encode(encodeWKTCRS(wktcrs, options?.["wkt-crs"])),
|
|
1756
|
+
encodeSync: (wktcrs, options) => new TextEncoder().encode(encodeWKTCRS(wktcrs, options?.["wkt-crs"])),
|
|
1757
|
+
encodeTextSync: (wktcrs, options) => encodeWKTCRS(wktcrs, options?.["wkt-crs"])
|
|
1758
|
+
};
|
|
1759
|
+
|
|
1760
|
+
// src/wkt-loader.ts
|
|
1761
|
+
var WKTWorkerLoader = {
|
|
1762
|
+
dataType: null,
|
|
1763
|
+
batchType: null,
|
|
1764
|
+
name: "WKT (Well-Known Text)",
|
|
1765
|
+
id: "wkt",
|
|
1766
|
+
module: "wkt",
|
|
1767
|
+
version: VERSION,
|
|
1768
|
+
worker: true,
|
|
1769
|
+
extensions: ["wkt"],
|
|
1770
|
+
mimeTypes: ["text/plain"],
|
|
1771
|
+
category: "geometry",
|
|
1772
|
+
text: true,
|
|
1773
|
+
tests: WKT_MAGIC_STRINGS,
|
|
1774
|
+
testText: isWKT,
|
|
1775
|
+
options: {
|
|
1776
|
+
wkt: {
|
|
1777
|
+
shape: "geojson-geometry",
|
|
1778
|
+
crs: true
|
|
1623
1779
|
}
|
|
1624
|
-
polygon.push(interiorRing);
|
|
1625
1780
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1781
|
+
};
|
|
1782
|
+
var WKTLoader = {
|
|
1783
|
+
...WKTWorkerLoader,
|
|
1784
|
+
parse: async (arrayBuffer, options) => convertWKTToGeometry(new TextDecoder().decode(arrayBuffer), options),
|
|
1785
|
+
parseTextSync: (string, options) => convertWKTToGeometry(string, options)
|
|
1786
|
+
};
|
|
1787
|
+
|
|
1788
|
+
// src/wkt-writer.ts
|
|
1789
|
+
var WKTWriter = {
|
|
1790
|
+
name: "WKT (Well Known Text)",
|
|
1791
|
+
id: "wkt",
|
|
1792
|
+
module: "wkt",
|
|
1793
|
+
version: VERSION,
|
|
1794
|
+
extensions: ["wkt"],
|
|
1795
|
+
mimeTypes: ["application/wkt", "text/plain"],
|
|
1796
|
+
text: true,
|
|
1797
|
+
encode: async (geometry) => convertGeometryToWKTSync(geometry),
|
|
1798
|
+
encodeSync: convertGeometryToWKTSync,
|
|
1799
|
+
encodeTextSync: convertGeometryToWKT,
|
|
1800
|
+
options: {
|
|
1801
|
+
wkt: {}
|
|
1637
1802
|
}
|
|
1638
|
-
|
|
1803
|
+
};
|
|
1804
|
+
function convertGeometryToWKTSync(geometry) {
|
|
1805
|
+
const wktString = convertGeometryToWKT(geometry);
|
|
1806
|
+
const wktTypedArray = new TextEncoder().encode(wktString);
|
|
1807
|
+
return wktTypedArray.buffer;
|
|
1639
1808
|
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1809
|
+
|
|
1810
|
+
// src/wkb-loader.ts
|
|
1811
|
+
var WKBWorkerLoader = {
|
|
1812
|
+
dataType: null,
|
|
1813
|
+
batchType: null,
|
|
1814
|
+
name: "WKB",
|
|
1815
|
+
id: "wkb",
|
|
1816
|
+
module: "wkt",
|
|
1817
|
+
version: VERSION,
|
|
1818
|
+
worker: true,
|
|
1819
|
+
category: "geometry",
|
|
1820
|
+
extensions: ["wkb"],
|
|
1821
|
+
mimeTypes: [],
|
|
1822
|
+
// TODO can we define static, serializable tests, eg. some binary strings?
|
|
1823
|
+
tests: [isWKB],
|
|
1824
|
+
options: {
|
|
1825
|
+
wkb: {
|
|
1826
|
+
shape: "geojson-geometry"
|
|
1652
1827
|
}
|
|
1653
|
-
coordinates.push(lineString);
|
|
1654
|
-
}
|
|
1655
|
-
return { type: "MultiLineString", coordinates };
|
|
1656
|
-
}
|
|
1657
|
-
function parseMultiPolygon3(reader, context) {
|
|
1658
|
-
if (context.isEmpty) {
|
|
1659
|
-
return { type: "MultiPolygon", coordinates: [] };
|
|
1660
1828
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
const interiorRingLength = reader.readVarInt();
|
|
1675
|
-
for (let k = 0; k < interiorRingLength; k++) {
|
|
1676
|
-
interiorRing.push(parseNextPoint(reader, context, previousPoint));
|
|
1677
|
-
}
|
|
1678
|
-
polygon.push(interiorRing);
|
|
1679
|
-
}
|
|
1680
|
-
polygons.push(polygon);
|
|
1829
|
+
};
|
|
1830
|
+
var WKBLoader = {
|
|
1831
|
+
...WKBWorkerLoader,
|
|
1832
|
+
parse: async (arrayBuffer, options) => parseWKB(arrayBuffer, options?.wkb),
|
|
1833
|
+
parseSync: (arrayBuffer, options) => parseWKB(arrayBuffer, options?.wkb)
|
|
1834
|
+
};
|
|
1835
|
+
function parseWKB(arrayBuffer, options) {
|
|
1836
|
+
const shape = options?.shape || "geojson-geometry";
|
|
1837
|
+
switch (shape) {
|
|
1838
|
+
case "geojson-geometry":
|
|
1839
|
+
return convertWKBToGeometry(arrayBuffer);
|
|
1840
|
+
default:
|
|
1841
|
+
throw new Error(shape);
|
|
1681
1842
|
}
|
|
1682
|
-
return { type: "MultiPolygon", coordinates: polygons };
|
|
1683
|
-
}
|
|
1684
|
-
function parseGeometryCollection2(reader, context) {
|
|
1685
|
-
return { type: "GeometryCollection", geometries: [] };
|
|
1686
|
-
}
|
|
1687
|
-
function zigZagDecode(value) {
|
|
1688
|
-
return value >> 1 ^ -(value & 1);
|
|
1689
|
-
}
|
|
1690
|
-
function makePointCoordinates(x, y, z, m) {
|
|
1691
|
-
return z !== void 0 ? m !== void 0 ? [x, y, z, m] : [x, y, z] : [x, y];
|
|
1692
|
-
}
|
|
1693
|
-
function makePreviousPoint(context) {
|
|
1694
|
-
return makePointCoordinates(0, 0, context.hasZ ? 0 : void 0, context.hasM ? 0 : void 0);
|
|
1695
1843
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1844
|
+
|
|
1845
|
+
// src/wkb-writer.ts
|
|
1846
|
+
var WKBWriter = {
|
|
1847
|
+
name: "WKB (Well Known Binary)",
|
|
1848
|
+
id: "wkb",
|
|
1849
|
+
module: "wkt",
|
|
1850
|
+
version: VERSION,
|
|
1851
|
+
extensions: ["wkb"],
|
|
1852
|
+
mimeTypes: ["application/wkb", "application/octet-stream"],
|
|
1853
|
+
options: {
|
|
1854
|
+
wkb: {
|
|
1855
|
+
hasZ: false,
|
|
1856
|
+
hasM: false
|
|
1857
|
+
}
|
|
1858
|
+
},
|
|
1859
|
+
async encode(data, options) {
|
|
1860
|
+
return convertGeometryToWKB(data);
|
|
1861
|
+
},
|
|
1862
|
+
encodeSync(data, options) {
|
|
1863
|
+
return convertGeometryToWKB(data);
|
|
1864
|
+
}
|
|
1865
|
+
};
|
|
1866
|
+
|
|
1867
|
+
// src/hex-wkb-loader.ts
|
|
1868
|
+
var HexWKBLoader = {
|
|
1869
|
+
dataType: null,
|
|
1870
|
+
batchType: null,
|
|
1871
|
+
name: "Hexadecimal WKB",
|
|
1872
|
+
id: "wkb",
|
|
1873
|
+
module: "wkt",
|
|
1874
|
+
version: VERSION,
|
|
1875
|
+
worker: true,
|
|
1876
|
+
category: "geometry",
|
|
1877
|
+
extensions: ["wkb"],
|
|
1878
|
+
mimeTypes: [],
|
|
1879
|
+
options: WKBLoader.options,
|
|
1880
|
+
text: true,
|
|
1881
|
+
testText: isHexWKB,
|
|
1882
|
+
// TODO - encoding here seems wasteful - extend hex transcoder?
|
|
1883
|
+
parse: async (arrayBuffer) => parseHexWKB(new TextDecoder().decode(arrayBuffer)),
|
|
1884
|
+
parseTextSync: parseHexWKB
|
|
1885
|
+
};
|
|
1886
|
+
function parseHexWKB(text, options) {
|
|
1887
|
+
const uint8Array = decodeHex(text);
|
|
1888
|
+
const binaryGeometry = convertWKBToGeometry(uint8Array.buffer);
|
|
1889
|
+
return binaryGeometry;
|
|
1702
1890
|
}
|
|
1703
|
-
function
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
if (context.hasZ) {
|
|
1707
|
-
previousPoint[2] += zigZagDecode(reader.readVarInt()) / context.zPrecisionFactor;
|
|
1891
|
+
function isHexWKB(string) {
|
|
1892
|
+
if (!string) {
|
|
1893
|
+
return false;
|
|
1708
1894
|
}
|
|
1709
|
-
if (
|
|
1710
|
-
|
|
1895
|
+
if (string.length < 10 || string.length % 2 !== 0) {
|
|
1896
|
+
return false;
|
|
1711
1897
|
}
|
|
1712
|
-
|
|
1898
|
+
if (!string.startsWith("00") && !string.startsWith("01")) {
|
|
1899
|
+
return false;
|
|
1900
|
+
}
|
|
1901
|
+
return /^[0-9a-fA-F]+$/.test(string.slice(2));
|
|
1713
1902
|
}
|
|
1714
1903
|
|
|
1715
1904
|
// src/twkb-loader.ts
|
|
@@ -1735,185 +1924,10 @@ var __exports__ = (() => {
|
|
|
1735
1924
|
};
|
|
1736
1925
|
var TWKBLoader = {
|
|
1737
1926
|
...TWKBWorkerLoader,
|
|
1738
|
-
parse: async (arrayBuffer) =>
|
|
1739
|
-
parseSync:
|
|
1927
|
+
parse: async (arrayBuffer) => convertTWKBToGeometry(arrayBuffer),
|
|
1928
|
+
parseSync: convertTWKBToGeometry
|
|
1740
1929
|
};
|
|
1741
1930
|
|
|
1742
|
-
// src/lib/encode-twkb.ts
|
|
1743
|
-
function encodeTWKB(geometry, options) {
|
|
1744
|
-
const writer = new BinaryWriter(0, true);
|
|
1745
|
-
const context = {
|
|
1746
|
-
...getTwkbPrecision(5, 0, 0),
|
|
1747
|
-
hasZ: options?.hasZ,
|
|
1748
|
-
hasM: options?.hasM
|
|
1749
|
-
};
|
|
1750
|
-
encodeGeometry(writer, geometry, context);
|
|
1751
|
-
return writer.arrayBuffer;
|
|
1752
|
-
}
|
|
1753
|
-
function encodeGeometry(writer, geometry, context) {
|
|
1754
|
-
switch (geometry.type) {
|
|
1755
|
-
case "Point":
|
|
1756
|
-
return encodePoint2(writer, context, geometry);
|
|
1757
|
-
case "LineString":
|
|
1758
|
-
return encodeLineString2(writer, context, geometry);
|
|
1759
|
-
case "Polygon":
|
|
1760
|
-
return encodePolygon2(writer, context, geometry);
|
|
1761
|
-
case "MultiPoint":
|
|
1762
|
-
return encodeMultiPoint2(writer, context, geometry);
|
|
1763
|
-
case "MultiLineString":
|
|
1764
|
-
return encodeMultiLineString2(writer, context, geometry);
|
|
1765
|
-
case "MultiPolygon":
|
|
1766
|
-
return encodeMultiPolygon2(writer, context, geometry);
|
|
1767
|
-
case "GeometryCollection":
|
|
1768
|
-
return encodeGeometryCollection2(writer, context, geometry);
|
|
1769
|
-
default:
|
|
1770
|
-
throw new Error("unsupported geometry type");
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
function encodePoint2(writer, context, point) {
|
|
1774
|
-
const isEmpty = point.coordinates.length === 0 || point[0] === "undefined" || point[1] === "undefined";
|
|
1775
|
-
writeTwkbHeader(writer, context, 1 /* Point */, isEmpty);
|
|
1776
|
-
if (!isEmpty) {
|
|
1777
|
-
const previousPoint = [0, 0, 0, 0];
|
|
1778
|
-
writeTwkbPoint(writer, context, point.coordinates, previousPoint);
|
|
1779
|
-
}
|
|
1780
|
-
}
|
|
1781
|
-
function encodeLineString2(writer, context, lineString) {
|
|
1782
|
-
const points = lineString.coordinates;
|
|
1783
|
-
const isEmpty = points.length === 0;
|
|
1784
|
-
writeTwkbHeader(writer, context, 2 /* LineString */, isEmpty);
|
|
1785
|
-
if (!isEmpty) {
|
|
1786
|
-
writer.writeVarInt(points.length);
|
|
1787
|
-
const previousPoint = [0, 0, 0, 0];
|
|
1788
|
-
for (const point of points) {
|
|
1789
|
-
writeTwkbPoint(writer, context, point, previousPoint);
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
return writer.arrayBuffer;
|
|
1793
|
-
}
|
|
1794
|
-
function encodePolygon2(writer, context, polygon) {
|
|
1795
|
-
const polygonRings = polygon.coordinates;
|
|
1796
|
-
const isEmpty = polygonRings.length === 0;
|
|
1797
|
-
writeTwkbHeader(writer, context, 3 /* Polygon */, isEmpty);
|
|
1798
|
-
if (!isEmpty) {
|
|
1799
|
-
writer.writeVarInt(polygonRings.length);
|
|
1800
|
-
const previousPoint = [0, 0, 0, 0];
|
|
1801
|
-
for (const ring of polygonRings) {
|
|
1802
|
-
writer.writeVarInt(ring.length);
|
|
1803
|
-
for (const point of ring) {
|
|
1804
|
-
writeTwkbPoint(writer, context, previousPoint, point);
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
return writer.arrayBuffer;
|
|
1809
|
-
}
|
|
1810
|
-
function encodeMultiPoint2(writer, context, multiPoint) {
|
|
1811
|
-
const points = multiPoint.coordinates;
|
|
1812
|
-
const isEmpty = points.length === 0;
|
|
1813
|
-
writeTwkbHeader(writer, context, 4 /* MultiPoint */, isEmpty);
|
|
1814
|
-
if (!isEmpty) {
|
|
1815
|
-
writer.writeVarInt(points.length);
|
|
1816
|
-
const previousPoint = [0, 0, 0, 0];
|
|
1817
|
-
for (let i = 0; i < points.length; i++) {
|
|
1818
|
-
writeTwkbPoint(writer, context, previousPoint, points[i]);
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1821
|
-
}
|
|
1822
|
-
function encodeMultiLineString2(writer, context, multiLineStrings) {
|
|
1823
|
-
const lineStrings = multiLineStrings.coordinates;
|
|
1824
|
-
const isEmpty = lineStrings.length === 0;
|
|
1825
|
-
writeTwkbHeader(writer, context, 5 /* MultiLineString */, isEmpty);
|
|
1826
|
-
if (!isEmpty) {
|
|
1827
|
-
writer.writeVarInt(lineStrings.length);
|
|
1828
|
-
const previousPoint = [0, 0, 0, 0];
|
|
1829
|
-
for (const lineString of lineStrings) {
|
|
1830
|
-
writer.writeVarInt(lineString.length);
|
|
1831
|
-
for (const point of lineString) {
|
|
1832
|
-
writeTwkbPoint(writer, context, previousPoint, point);
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
return writer.arrayBuffer;
|
|
1837
|
-
}
|
|
1838
|
-
function encodeMultiPolygon2(writer, context, multiPolygon) {
|
|
1839
|
-
const { coordinates } = multiPolygon;
|
|
1840
|
-
const isEmpty = coordinates.length === 0;
|
|
1841
|
-
writeTwkbHeader(writer, context, 6 /* MultiPolygon */, isEmpty);
|
|
1842
|
-
if (!isEmpty) {
|
|
1843
|
-
const polygons = coordinates;
|
|
1844
|
-
writer.writeVarInt(polygons.length);
|
|
1845
|
-
const previousPoint = [0, 0, 0, 0];
|
|
1846
|
-
for (const polygonRings of polygons) {
|
|
1847
|
-
writer.writeVarInt(polygonRings.length);
|
|
1848
|
-
for (const ring of polygonRings) {
|
|
1849
|
-
writer.writeVarInt(ring.length);
|
|
1850
|
-
for (const point of ring) {
|
|
1851
|
-
writeTwkbPoint(writer, context, previousPoint, point);
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
function encodeGeometryCollection2(writer, context, geometryCollection) {
|
|
1858
|
-
const { geometries } = geometryCollection;
|
|
1859
|
-
const isEmpty = geometries.length === 0;
|
|
1860
|
-
writeTwkbHeader(writer, context, 7 /* GeometryCollection */, isEmpty);
|
|
1861
|
-
if (geometries.length > 0) {
|
|
1862
|
-
writer.writeVarInt(geometries.length);
|
|
1863
|
-
for (const geometry of geometries) {
|
|
1864
|
-
encodeGeometry(writer, geometry, context);
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
|
-
function writeTwkbHeader(writer, context, geometryType, isEmpty) {
|
|
1869
|
-
const type = (zigZagEncode(context.xy) << 4) + geometryType;
|
|
1870
|
-
let metadataHeader = context.hasZ || context.hasM ? 1 << 3 : 0;
|
|
1871
|
-
metadataHeader += isEmpty ? 1 << 4 : 0;
|
|
1872
|
-
writer.writeUInt8(type);
|
|
1873
|
-
writer.writeUInt8(metadataHeader);
|
|
1874
|
-
if (context.hasZ || context.hasM) {
|
|
1875
|
-
let extendedPrecision = 0;
|
|
1876
|
-
if (context.hasZ) {
|
|
1877
|
-
extendedPrecision |= 1;
|
|
1878
|
-
}
|
|
1879
|
-
if (context.hasM) {
|
|
1880
|
-
extendedPrecision |= 2;
|
|
1881
|
-
}
|
|
1882
|
-
writer.writeUInt8(extendedPrecision);
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
function writeTwkbPoint(writer, context, point, previousPoint) {
|
|
1886
|
-
const x = point[0] * context.xyFactor;
|
|
1887
|
-
const y = point[1] * context.xyFactor;
|
|
1888
|
-
const z = point[2] * context.zFactor;
|
|
1889
|
-
const m = point[3] * context.mFactor;
|
|
1890
|
-
writer.writeVarInt(zigZagEncode(x - previousPoint[0]));
|
|
1891
|
-
writer.writeVarInt(zigZagEncode(y - previousPoint[1]));
|
|
1892
|
-
if (context.hasZ) {
|
|
1893
|
-
writer.writeVarInt(zigZagEncode(z - previousPoint[2]));
|
|
1894
|
-
}
|
|
1895
|
-
if (context.hasM) {
|
|
1896
|
-
writer.writeVarInt(zigZagEncode(m - previousPoint[3]));
|
|
1897
|
-
}
|
|
1898
|
-
previousPoint[0] = x;
|
|
1899
|
-
previousPoint[1] = y;
|
|
1900
|
-
previousPoint[2] = z;
|
|
1901
|
-
previousPoint[3] = m;
|
|
1902
|
-
}
|
|
1903
|
-
function zigZagEncode(value) {
|
|
1904
|
-
return value << 1 ^ value >> 31;
|
|
1905
|
-
}
|
|
1906
|
-
function getTwkbPrecision(xyPrecision, zPrecision, mPrecision) {
|
|
1907
|
-
return {
|
|
1908
|
-
xy: xyPrecision,
|
|
1909
|
-
z: zPrecision,
|
|
1910
|
-
m: mPrecision,
|
|
1911
|
-
xyFactor: Math.pow(10, xyPrecision),
|
|
1912
|
-
zFactor: Math.pow(10, zPrecision),
|
|
1913
|
-
mFactor: Math.pow(10, mPrecision)
|
|
1914
|
-
};
|
|
1915
|
-
}
|
|
1916
|
-
|
|
1917
1931
|
// src/twkb-writer.ts
|
|
1918
1932
|
var TWKBWriter = {
|
|
1919
1933
|
name: "TWKB (Tiny Well Known Binary)",
|
|
@@ -1921,8 +1935,9 @@ var __exports__ = (() => {
|
|
|
1921
1935
|
module: "wkt",
|
|
1922
1936
|
version: VERSION,
|
|
1923
1937
|
extensions: ["twkb"],
|
|
1924
|
-
|
|
1925
|
-
|
|
1938
|
+
mimeTypes: ["application/text"],
|
|
1939
|
+
encode: async (geometry, options) => convertGeometryToTWKB(geometry, options?.twkb),
|
|
1940
|
+
encodeSync: (geometry, options) => convertGeometryToTWKB(geometry, options?.twkb),
|
|
1926
1941
|
options: {
|
|
1927
1942
|
twkb: {
|
|
1928
1943
|
hasZ: false,
|