@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.
Files changed (111) hide show
  1. package/dist/dist.dev.js +1281 -1266
  2. package/dist/dist.min.js +2 -2
  3. package/dist/hex-wkb-loader.d.ts +6 -5
  4. package/dist/hex-wkb-loader.d.ts.map +1 -1
  5. package/dist/hex-wkb-loader.js +4 -4
  6. package/dist/index.cjs +51 -1622
  7. package/dist/index.cjs.map +4 -4
  8. package/dist/index.d.ts +0 -5
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +0 -5
  11. package/dist/lib/version.d.ts.map +1 -0
  12. package/dist/lib/{utils/version.js → version.js} +1 -1
  13. package/dist/twkb-loader.d.ts +3 -3
  14. package/dist/twkb-loader.d.ts.map +1 -1
  15. package/dist/twkb-loader.js +4 -4
  16. package/dist/twkb-writer.d.ts +2 -1
  17. package/dist/twkb-writer.d.ts.map +1 -1
  18. package/dist/twkb-writer.js +5 -4
  19. package/dist/wkb-loader.d.ts +13 -11
  20. package/dist/wkb-loader.d.ts.map +1 -1
  21. package/dist/wkb-loader.js +14 -6
  22. package/dist/wkb-writer.d.ts +3 -2
  23. package/dist/wkb-writer.d.ts.map +1 -1
  24. package/dist/wkb-writer.js +5 -4
  25. package/dist/wkt-crs-loader.d.ts +1 -1
  26. package/dist/wkt-crs-loader.d.ts.map +1 -1
  27. package/dist/wkt-crs-loader.js +2 -2
  28. package/dist/wkt-crs-writer.d.ts +1 -1
  29. package/dist/wkt-crs-writer.d.ts.map +1 -1
  30. package/dist/wkt-crs-writer.js +2 -2
  31. package/dist/wkt-loader.d.ts +2 -2
  32. package/dist/wkt-loader.d.ts.map +1 -1
  33. package/dist/wkt-loader.js +4 -4
  34. package/dist/wkt-worker.js +26 -13
  35. package/dist/wkt-writer.d.ts +6 -5
  36. package/dist/wkt-writer.d.ts.map +1 -1
  37. package/dist/wkt-writer.js +10 -7
  38. package/package.json +6 -6
  39. package/src/hex-wkb-loader.ts +8 -8
  40. package/src/index.ts +0 -10
  41. package/src/twkb-loader.ts +5 -5
  42. package/src/twkb-writer.ts +6 -5
  43. package/src/wkb-loader.ts +24 -12
  44. package/src/wkb-writer.ts +8 -7
  45. package/src/wkt-crs-loader.ts +3 -3
  46. package/src/wkt-crs-writer.ts +3 -5
  47. package/src/wkt-loader.ts +6 -5
  48. package/src/wkt-writer.ts +11 -8
  49. package/dist/lib/encode-twkb.d.ts +0 -6
  50. package/dist/lib/encode-twkb.d.ts.map +0 -1
  51. package/dist/lib/encode-twkb.js +0 -195
  52. package/dist/lib/encode-wkb.d.ts +0 -33
  53. package/dist/lib/encode-wkb.d.ts.map +0 -1
  54. package/dist/lib/encode-wkb.js +0 -286
  55. package/dist/lib/encode-wkt-crs.d.ts +0 -10
  56. package/dist/lib/encode-wkt-crs.d.ts.map +0 -1
  57. package/dist/lib/encode-wkt-crs.js +0 -35
  58. package/dist/lib/encode-wkt.d.ts +0 -8
  59. package/dist/lib/encode-wkt.d.ts.map +0 -1
  60. package/dist/lib/encode-wkt.js +0 -47
  61. package/dist/lib/parse-hex-wkb.d.ts +0 -1
  62. package/dist/lib/parse-hex-wkb.d.ts.map +0 -1
  63. package/dist/lib/parse-hex-wkb.js +0 -1
  64. package/dist/lib/parse-twkb.d.ts +0 -9
  65. package/dist/lib/parse-twkb.d.ts.map +0 -1
  66. package/dist/lib/parse-twkb.js +0 -253
  67. package/dist/lib/parse-wkb-header.d.ts +0 -39
  68. package/dist/lib/parse-wkb-header.d.ts.map +0 -1
  69. package/dist/lib/parse-wkb-header.js +0 -134
  70. package/dist/lib/parse-wkb.d.ts +0 -5
  71. package/dist/lib/parse-wkb.d.ts.map +0 -1
  72. package/dist/lib/parse-wkb.js +0 -241
  73. package/dist/lib/parse-wkt-crs.d.ts +0 -15
  74. package/dist/lib/parse-wkt-crs.d.ts.map +0 -1
  75. package/dist/lib/parse-wkt-crs.js +0 -120
  76. package/dist/lib/parse-wkt.d.ts +0 -30
  77. package/dist/lib/parse-wkt.d.ts.map +0 -1
  78. package/dist/lib/parse-wkt.js +0 -288
  79. package/dist/lib/utils/base64-encoder.d.ts +0 -5
  80. package/dist/lib/utils/base64-encoder.d.ts.map +0 -1
  81. package/dist/lib/utils/base64-encoder.js +0 -153
  82. package/dist/lib/utils/binary-reader.d.ts +0 -18
  83. package/dist/lib/utils/binary-reader.d.ts.map +0 -1
  84. package/dist/lib/utils/binary-reader.js +0 -69
  85. package/dist/lib/utils/binary-writer.d.ts +0 -28
  86. package/dist/lib/utils/binary-writer.d.ts.map +0 -1
  87. package/dist/lib/utils/binary-writer.js +0 -121
  88. package/dist/lib/utils/hex-encoder.d.ts +0 -15
  89. package/dist/lib/utils/hex-encoder.d.ts.map +0 -1
  90. package/dist/lib/utils/hex-encoder.js +0 -54
  91. package/dist/lib/utils/hex-transcoder.d.ts +0 -15
  92. package/dist/lib/utils/hex-transcoder.d.ts.map +0 -1
  93. package/dist/lib/utils/hex-transcoder.js +0 -50
  94. package/dist/lib/utils/version.d.ts.map +0 -1
  95. package/src/lib/encode-twkb.ts +0 -308
  96. package/src/lib/encode-wkb.ts +0 -390
  97. package/src/lib/encode-wkt-crs.ts +0 -41
  98. package/src/lib/encode-wkt.ts +0 -56
  99. package/src/lib/parse-hex-wkb.ts +0 -0
  100. package/src/lib/parse-twkb.ts +0 -365
  101. package/src/lib/parse-wkb-header.ts +0 -174
  102. package/src/lib/parse-wkb.ts +0 -343
  103. package/src/lib/parse-wkt-crs.ts +0 -149
  104. package/src/lib/parse-wkt.ts +0 -327
  105. package/src/lib/utils/base64-encoder.ts +0 -157
  106. package/src/lib/utils/binary-reader.ts +0 -76
  107. package/src/lib/utils/binary-writer.ts +0 -127
  108. package/src/lib/utils/hex-encoder.ts +0 -60
  109. package/src/lib/utils/hex-transcoder.ts +0 -54
  110. /package/dist/lib/{utils/version.d.ts → version.d.ts} +0 -0
  111. /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/utils/version.ts
72
- var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
73
-
74
- // src/lib/parse-wkt-crs.ts
75
- function parseWKTCRS(wkt, options) {
76
- if (options?.debug) {
77
- console.log("[wktcrs] parse starting with\n", wkt);
78
- }
79
- wkt = wkt.replace(/[A-Z][A-Z\d_]+\[/gi, (match) => `["${match.substr(0, match.length - 1)}",`);
80
- wkt = wkt.replace(/, ?([A-Z][A-Z\d_]+[,\]])/gi, (match, p1) => {
81
- const varname = p1.substr(0, p1.length - 1);
82
- return `,"${options?.raw ? "raw:" : ""}${varname}"${p1[p1.length - 1]}`;
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
- let data;
93
- try {
94
- data = JSON.parse(wkt);
95
- } catch (error) {
96
- console.error(`[wktcrs] failed to parse '${wkt}'`);
97
- throw error;
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
- if (options?.debug) {
100
- console.log(`[wktcrs] json parsed: '${wkt}'`);
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
- function process(data2, parent) {
103
- const kw = data2[0];
104
- data2.forEach(function(it) {
105
- if (Array.isArray(it)) {
106
- process(it, data2);
107
- }
108
- });
109
- const kwarr = `MULTIPLE_${kw}`;
110
- if (kwarr in parent) {
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 result = process(data, [data]);
121
- if (options?.debug) {
122
- console.log("[wktcrs] parse returning", result);
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
- if (options?.sort) {
125
- sort(result, options);
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 result;
131
+ return { type: "Point", coordinates: coordinates[0] };
128
132
  }
129
- function sort(data, options) {
130
- const keys = Object.keys(data).filter((k) => !/\d+/.test(k));
131
- const keywords = options?.keywords || [];
132
- if (!options?.keywords) {
133
- const counts = {};
134
- if (Array.isArray(data)) {
135
- data.forEach((it) => {
136
- if (Array.isArray(it) && it.length >= 2 && typeof it[1] === "string") {
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
- keys.forEach((key) => {
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/wkt-crs-loader.ts
174
- var WKTCRSLoader = {
175
- dataType: null,
176
- batchType: null,
177
- name: "WKT CRS (Well-Known Text Coordinate Reference System)",
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 [kw, ...attrs] = wkt;
199
- const str = `${kw}[${attrs.map((attr) => {
200
- if (Array.isArray(attr)) {
201
- return encodeWKTCRS(attr, options);
202
- } else if (typeof attr === "number") {
203
- return attr.toString();
204
- } else if (typeof attr === "string") {
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
- throw new Error(`[wktcrs] unexpected attribute "${attr}"`);
211
- }).join(",")}]`;
212
- return str;
161
+ }
162
+ return buffer;
213
163
  }
214
164
 
215
- // src/wkt-crs-writer.ts
216
- var WKTCRSWriter = {
217
- name: "WKT CRS (Well-Known Text Coordinate Reference System)",
218
- id: "wkt-crs",
219
- module: "wkt-crs",
220
- version: VERSION,
221
- worker: true,
222
- extensions: [],
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 parseWKT(input, options) {
251
- return parseWKTToGeometry(input, options);
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 parseWKTToGeometry(input, options) {
254
- const parts = input.split(";");
255
- let _ = parts.pop();
256
- const srid = (parts.shift() || "").split("=").pop();
257
- const state = { parts, _, i: 0 };
258
- const geometry = parseGeometry(state);
259
- return options?.wkt?.crs ? addCRS(geometry, srid) : geometry;
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
- function parseGeometry(state) {
262
- return parsePoint(state) || parseLineString(state) || parsePolygon(state) || parseMultiPoint(state) || parseMultiLineString(state) || parseMultiPolygon(state) || parseGeometryCollection(state);
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 addCRS(obj, srid) {
265
- if (obj && srid?.match(/\d+/)) {
266
- const crs = {
267
- type: "name",
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
- return obj;
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 parsePoint(state) {
277
- if (!$(/^(POINT(\sz)?)/i, state)) {
278
- return null;
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
- white(state);
281
- if (!$(/^(\()/, state)) {
282
- return null;
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 c = coords(state);
285
- if (!c) {
286
- return null;
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
- white(state);
289
- if (!$(/^(\))/, state)) {
290
- return null;
268
+ const geometryFlags = geometry - geometryType;
269
+ if (geometryFlags === 0 || geometryFlags === 1e3 || geometryFlags === 2e3 || geometryFlags === 3e3) {
270
+ return true;
291
271
  }
292
- return {
293
- type: "Point",
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
- white(state);
302
- const newCoordsFormat = state._?.substring(state._?.indexOf("(") + 1, state._.length - 1).replace(/\(/g, "").replace(/\)/g, "");
303
- state._ = "MULTIPOINT (" + newCoordsFormat + ")";
304
- const c = multicoords(state);
305
- if (!c) {
306
- return null;
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
- white(state);
309
- return {
310
- type: "MultiPoint",
311
- coordinates: c
312
- };
282
+ return true;
313
283
  }
314
- function parseLineString(state) {
315
- if (!$(/^(LINESTRING(\sz)?)/i, state)) {
316
- return null;
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
- white(state);
319
- if (!$(/^(\()/, state)) {
320
- return null;
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 c = coords(state);
323
- if (!c) {
324
- return null;
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 (!$(/^(\))/, state)) {
327
- return null;
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
- function parseMultiLineString(state) {
335
- if (!$(/^(MULTILINESTRING)/i, state))
336
- return null;
337
- white(state);
338
- const c = multicoords(state);
339
- if (!c) {
340
- return null;
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 parsePolygon(state) {
351
- if (!$(/^(POLYGON(\sz)?)/i, state)) {
352
- return null;
353
- }
354
- white(state);
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
- // @ts-ignore
361
- type: "Polygon",
362
- // @ts-expect-error
363
- coordinates: c
387
+ geometry: { type: "Point", positions: { value: positions, size: dimension } },
388
+ offset
364
389
  };
365
390
  }
366
- function parseMultiPolygon(state) {
367
- if (!$(/^(MULTIPOLYGON)/i, state)) {
368
- return null;
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
- white(state);
371
- const c = multicoords(state);
372
- if (!c) {
373
- return null;
399
+ const pathIndices = [0];
400
+ if (nPoints > 0) {
401
+ pathIndices.push(nPoints);
374
402
  }
375
403
  return {
376
- type: "MultiPolygon",
377
- // @ts-expect-error
378
- coordinates: c
379
- };
380
- }
381
- function parseGeometryCollection(state) {
382
- const geometries = [];
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/wkt-loader.ts
476
- var WKTWorkerLoader = {
477
- dataType: null,
478
- batchType: null,
479
- name: "WKT (Well-Known Text)",
480
- id: "wkt",
481
- module: "wkt",
482
- version: VERSION,
483
- worker: true,
484
- extensions: ["wkt"],
485
- mimeTypes: ["text/plain"],
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
- var WKTLoader = {
498
- ...WKTWorkerLoader,
499
- parse: async (arrayBuffer, options) => parseWKT(new TextDecoder().decode(arrayBuffer), options),
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
- switch (geometry.type) {
509
- case "Point":
510
- return `POINT ${wrapParens(pairWKT(geometry.coordinates))}`;
511
- case "LineString":
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 pairWKT(c) {
528
- return c.join(" ");
529
- }
530
- function ringWKT(r) {
531
- return r.map(pairWKT).join(", ");
532
- }
533
- function ringsWKT(r) {
534
- return r.map(ringWKT).map(wrapParens).join(", ");
535
- }
536
- function multiRingsWKT(r) {
537
- return r.map(ringsWKT).map(wrapParens).join(", ");
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 wrapParens(s) {
540
- return `(${s})`;
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
- // src/wkt-writer.ts
544
- var WKTWriter = {
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
- // ../gis/src/lib/binary-features/binary-to-geojson.ts
563
- function binaryToGeometry(data, startIndex, endIndex) {
564
- switch (data.type) {
565
- case "Point":
566
- return pointToGeoJson(data, startIndex, endIndex);
567
- case "LineString":
568
- return lineStringToGeoJson(data, startIndex, endIndex);
569
- case "Polygon":
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 polygonToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
577
- const { positions } = data;
578
- const polygonIndices = data.polygonIndices.value.filter((x) => x >= startIndex && x <= endIndex);
579
- const primitivePolygonIndices = data.primitivePolygonIndices.value.filter(
580
- (x) => x >= startIndex && x <= endIndex
581
- );
582
- const multi = polygonIndices.length > 2;
583
- if (!multi) {
584
- const coordinates2 = [];
585
- for (let i = 0; i < primitivePolygonIndices.length - 1; i++) {
586
- const startRingIndex = primitivePolygonIndices[i];
587
- const endRingIndex = primitivePolygonIndices[i + 1];
588
- const ringCoordinates = ringToGeoJson(positions, startRingIndex, endRingIndex);
589
- coordinates2.push(ringCoordinates);
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
- return { type: "Polygon", coordinates: coordinates2 };
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 < polygonIndices.length - 1; i++) {
595
- const startPolygonIndex = polygonIndices[i];
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: "MultiPolygon", coordinates };
922
+ return { type: "MultiPoint", coordinates };
605
923
  }
606
- function lineStringToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
607
- const { positions } = data;
608
- const pathIndices = data.pathIndices.value.filter((x) => x >= startIndex && x <= endIndex);
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 < pathIndices.length - 1; i++) {
616
- const ringCoordinates = ringToGeoJson(positions, pathIndices[i], pathIndices[i + 1]);
617
- coordinates.push(ringCoordinates);
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 pointToGeoJson(data, startIndex, endIndex) {
622
- const { positions } = data;
623
- const coordinates = ringToGeoJson(positions, startIndex, endIndex);
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
- return { type: "Point", coordinates: coordinates[0] };
629
- }
630
- function ringToGeoJson(positions, startIndex, endIndex) {
631
- startIndex = startIndex || 0;
632
- endIndex = endIndex || positions.value.length / positions.size;
633
- const ringCoordinates = [];
634
- for (let j = startIndex; j < endIndex; j++) {
635
- const coord = Array();
636
- for (let k = j * positions.size; k < (j + 1) * positions.size; k++) {
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
- ringCoordinates.push(coord);
640
- }
641
- return ringCoordinates;
642
- }
643
-
644
- // src/lib/parse-wkb-header.ts
645
- var EWKB_FLAG_Z = 2147483648;
646
- var EWKB_FLAG_M = 1073741824;
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 true;
966
+ return { type: "MultiPolygon", coordinates: polygons };
679
967
  }
680
- function parseWKBHeader(dataView, target) {
681
- const wkbHeader = Object.assign(target || {}, {
682
- type: "wkb",
683
- geometryType: 1,
684
- dimensions: 2,
685
- coordinates: "xy",
686
- littleEndian: true,
687
- byteOffset: 0
688
- });
689
- wkbHeader.littleEndian = dataView.getUint8(wkbHeader.byteOffset) === 1;
690
- wkbHeader.byteOffset++;
691
- const geometryCode = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
692
- wkbHeader.byteOffset += 4;
693
- wkbHeader.geometryType = geometryCode & 7;
694
- const isoType = (geometryCode - wkbHeader.geometryType) / 1e3;
695
- switch (isoType) {
696
- case 0:
697
- break;
698
- case 1:
699
- wkbHeader.type = "iso-wkb";
700
- wkbHeader.dimensions = 3;
701
- wkbHeader.coordinates = "xyz";
702
- break;
703
- case 2:
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 (ewkbSRID) {
733
- wkbHeader.type = "ewkb";
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 wkbHeader;
996
+ return previousPoint.slice();
738
997
  }
739
998
 
740
- // src/lib/parse-wkb.ts
741
- function parseWKB(arrayBuffer, options) {
742
- const binaryGeometry = parseWKBToBinary(arrayBuffer, options);
743
- const shape = options?.wkb?.shape || "binary-geometry";
744
- switch (shape) {
745
- case "binary-geometry":
746
- return binaryGeometry;
747
- case "geojson-geometry":
748
- return binaryToGeometry(binaryGeometry);
749
- case "geometry":
750
- console.error('WKBLoader: "geometry" shape is deprecated, use "binary-geometry" instead');
751
- return binaryToGeometry(binaryGeometry);
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(shape);
1017
+ throw new Error(
1018
+ "convertGeometryToWKT requires a valid GeoJSON Geometry (not Feature) as input"
1019
+ );
754
1020
  }
755
1021
  }
756
- function parseWKBToBinary(arrayBuffer, options) {
757
- const dataView = new DataView(arrayBuffer);
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 parsePoint2(dataView, offset, dimension, littleEndian) {
788
- const positions = new Float64Array(dimension);
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 parseLineString2(dataView, offset, dimension, littleEndian) {
799
- const nPoints = dataView.getUint32(offset, littleEndian);
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
- var cumulativeSum = (sum) => (value) => sum += value;
820
- function parsePolygon2(dataView, offset, dimension, littleEndian) {
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 parseMultiPoint2(dataView, offset, dimension, littleEndian) {
851
- const nPoints = dataView.getUint32(offset, littleEndian);
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/wkb-loader.ts
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/encode-wkb.ts
1106
- function encodeWKB(geometry, options = {}) {
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 = encodeWKB(geometry, options);
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-writer.ts
1341
- var WKBWriter = {
1342
- name: "WKB (Well Known Binary)",
1343
- id: "wkb",
1344
- module: "wkt",
1345
- version: VERSION,
1346
- extensions: ["wkb"],
1347
- options: {
1348
- wkb: {
1349
- hasZ: false,
1350
- hasM: false
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
- // src/lib/utils/hex-transcoder.ts
1362
- var alphabet = "0123456789abcdef";
1363
- var encodeLookup = [];
1364
- var decodeLookup = [];
1365
- for (let i = 0; i < 256; i++) {
1366
- encodeLookup[i] = alphabet[i >> 4 & 15] + alphabet[i & 15];
1367
- if (i < 16) {
1368
- if (i < 10) {
1369
- decodeLookup[48 + i] = i;
1370
- } else {
1371
- decodeLookup[97 - 10 + i] = i;
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 encodeHex(array) {
1376
- const length = array.length;
1377
- let string = "";
1378
- let i = 0;
1379
- while (i < length) {
1380
- string += encodeLookup[array[i++]];
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 decodeHex(string) {
1385
- const sizeof = string.length >> 1;
1386
- const length = sizeof << 1;
1387
- const array = new Uint8Array(sizeof);
1388
- let n = 0;
1389
- let i = 0;
1390
- while (i < length) {
1391
- array[n++] = decodeLookup[string.charCodeAt(i++)] << 4 | decodeLookup[string.charCodeAt(i++)];
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 array;
1490
+ return writer.arrayBuffer;
1394
1491
  }
1395
-
1396
- // src/hex-wkb-loader.ts
1397
- var HexWKBLoader = {
1398
- dataType: null,
1399
- batchType: null,
1400
- name: "Hexadecimal WKB",
1401
- id: "wkb",
1402
- module: "wkt",
1403
- version: VERSION,
1404
- worker: true,
1405
- category: "geometry",
1406
- extensions: ["wkb"],
1407
- mimeTypes: [],
1408
- options: WKBLoader.options,
1409
- text: true,
1410
- testText: isHexWKB,
1411
- // TODO - encoding here seems wasteful - extend hex transcoder?
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
- if (!string.startsWith("00") && !string.startsWith("01")) {
1428
- return false;
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
- // src/lib/utils/binary-reader.ts
1434
- var BinaryReader = class {
1435
- arrayBuffer;
1436
- dataView;
1437
- byteOffset;
1438
- littleEndian;
1439
- constructor(arrayBuffer, isBigEndian = false) {
1440
- this.arrayBuffer = arrayBuffer;
1441
- this.dataView = new DataView(arrayBuffer);
1442
- this.byteOffset = 0;
1443
- this.littleEndian = !isBigEndian;
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
- readUInt8() {
1446
- const value = this.dataView.getUint8(this.byteOffset);
1447
- this.byteOffset += 1;
1448
- return value;
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
- readUInt16() {
1451
- const value = this.dataView.getUint16(this.byteOffset, this.littleEndian);
1452
- this.byteOffset += 2;
1453
- return value;
1549
+ if (context.hasM) {
1550
+ writer.writeVarInt(zigZagEncode(m - previousPoint[3]));
1454
1551
  }
1455
- readUInt32() {
1456
- const value = this.dataView.getUint32(this.byteOffset, this.littleEndian);
1457
- this.byteOffset += 4;
1458
- return value;
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
- readInt8() {
1461
- const value = this.dataView.getInt8(this.byteOffset);
1462
- this.byteOffset += 1;
1463
- return value;
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
- readInt16() {
1466
- const value = this.dataView.getInt16(this.byteOffset, this.littleEndian);
1467
- this.byteOffset += 2;
1468
- return value;
1586
+ if (options?.debug) {
1587
+ console.log(`[wktcrs] json'd wkt: '${wkt}'`);
1469
1588
  }
1470
- readInt32() {
1471
- const value = this.dataView.getInt32(this.byteOffset, this.littleEndian);
1472
- this.byteOffset += 4;
1473
- return value;
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
- readFloat() {
1476
- const value = this.dataView.getFloat32(this.byteOffset, this.littleEndian);
1477
- this.byteOffset += 4;
1478
- return value;
1596
+ if (options?.debug) {
1597
+ console.log(`[wktcrs] json parsed: '${wkt}'`);
1479
1598
  }
1480
- readDouble() {
1481
- const value = this.dataView.getFloat64(this.byteOffset, this.littleEndian);
1482
- this.byteOffset += 8;
1483
- return value;
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
- readVarInt() {
1486
- let result = 0;
1487
- let bytesRead = 0;
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 true;
1624
+ return result;
1508
1625
  }
1509
- function parseTWKBGeometry(arrayBuffer) {
1510
- const binaryReader = new BinaryReader(arrayBuffer);
1511
- const context = parseTWKBHeader(binaryReader);
1512
- if (context.hasSizeAttribute) {
1513
- binaryReader.readVarInt();
1514
- }
1515
- if (context.hasBoundingBox) {
1516
- let dimensions = 2;
1517
- if (context.hasZ) {
1518
- dimensions++;
1519
- }
1520
- if (context.hasM) {
1521
- dimensions++;
1522
- }
1523
- for (let i = 0; i < dimensions; i++) {
1524
- binaryReader.readVarInt();
1525
- binaryReader.readVarInt();
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
- return parseGeometry2(binaryReader, context, context.geometryType);
1529
- }
1530
- function parseTWKBHeader(binaryReader) {
1531
- const type = binaryReader.readUInt8();
1532
- const metadataHeader = binaryReader.readUInt8();
1533
- const geometryType = type & 15;
1534
- const precision = zigZagDecode(type >> 4);
1535
- const hasExtendedPrecision = Boolean(metadataHeader >> 3 & 1);
1536
- let hasZ = false;
1537
- let hasM = false;
1538
- let zPrecision = 0;
1539
- let zPrecisionFactor = 1;
1540
- let mPrecision = 0;
1541
- let mPrecisionFactor = 1;
1542
- if (hasExtendedPrecision) {
1543
- const extendedPrecision = binaryReader.readUInt8();
1544
- hasZ = (extendedPrecision & 1) === 1;
1545
- hasM = (extendedPrecision & 2) === 2;
1546
- zPrecision = zigZagDecode((extendedPrecision & 28) >> 2);
1547
- zPrecisionFactor = Math.pow(10, zPrecision);
1548
- mPrecision = zigZagDecode((extendedPrecision & 224) >> 5);
1549
- mPrecisionFactor = Math.pow(10, mPrecision);
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
- function parseGeometry2(binaryReader, context, geometryType) {
1569
- switch (geometryType) {
1570
- case 1 /* Point */:
1571
- return parsePoint3(binaryReader, context);
1572
- case 2 /* LineString */:
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
- function parsePoint3(reader, context) {
1589
- if (context.isEmpty) {
1590
- return { type: "Point", coordinates: [] };
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 parseLineString3(reader, context) {
1595
- if (context.isEmpty) {
1596
- return { type: "LineString", coordinates: [] };
1597
- }
1598
- const pointCount = reader.readVarInt();
1599
- const previousPoint = makePreviousPoint(context);
1600
- const points = [];
1601
- for (let i = 0; i < pointCount; i++) {
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 { type: "LineString", coordinates: points };
1715
+ return array;
1605
1716
  }
1606
- function parsePolygon3(reader, context) {
1607
- if (context.isEmpty) {
1608
- return { type: "Polygon", coordinates: [] };
1609
- }
1610
- const ringCount = reader.readVarInt();
1611
- const previousPoint = makePreviousPoint(context);
1612
- const exteriorRingLength = reader.readVarInt();
1613
- const exteriorRing = [];
1614
- for (let i = 0; i < exteriorRingLength; i++) {
1615
- exteriorRing.push(parseNextPoint(reader, context, previousPoint));
1616
- }
1617
- const polygon = [exteriorRing];
1618
- for (let i = 1; i < ringCount; i++) {
1619
- const interiorRingCount = reader.readVarInt();
1620
- const interiorRing = [];
1621
- for (let j = 0; j < interiorRingCount; j++) {
1622
- interiorRing.push(parseNextPoint(reader, context, previousPoint));
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
- return { type: "Polygon", coordinates: polygon };
1627
- }
1628
- function parseMultiPoint3(reader, context) {
1629
- if (context.isEmpty) {
1630
- return { type: "MultiPoint", coordinates: [] };
1631
- }
1632
- const previousPoint = makePreviousPoint(context);
1633
- const pointCount = reader.readVarInt();
1634
- const coordinates = [];
1635
- for (let i = 0; i < pointCount; i++) {
1636
- coordinates.push(parseNextPoint(reader, context, previousPoint));
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
- return { type: "MultiPoint", coordinates };
1803
+ };
1804
+ function convertGeometryToWKTSync(geometry) {
1805
+ const wktString = convertGeometryToWKT(geometry);
1806
+ const wktTypedArray = new TextEncoder().encode(wktString);
1807
+ return wktTypedArray.buffer;
1639
1808
  }
1640
- function parseMultiLineString3(reader, context) {
1641
- if (context.isEmpty) {
1642
- return { type: "MultiLineString", coordinates: [] };
1643
- }
1644
- const previousPoint = makePreviousPoint(context);
1645
- const lineStringCount = reader.readVarInt();
1646
- const coordinates = [];
1647
- for (let i = 0; i < lineStringCount; i++) {
1648
- const pointCount = reader.readVarInt();
1649
- const lineString = [];
1650
- for (let j = 0; j < pointCount; j++) {
1651
- lineString.push(parseNextPoint(reader, context, previousPoint));
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
- const previousPoint = makePreviousPoint(context);
1662
- const polygonCount = reader.readVarInt();
1663
- const polygons = [];
1664
- for (let i = 0; i < polygonCount; i++) {
1665
- const ringCount = reader.readVarInt();
1666
- const exteriorPointCount = reader.readVarInt();
1667
- const exteriorRing = [];
1668
- for (let j = 0; j < exteriorPointCount; j++) {
1669
- exteriorRing.push(parseNextPoint(reader, context, previousPoint));
1670
- }
1671
- const polygon = exteriorRing ? [exteriorRing] : [];
1672
- for (let j = 1; j < ringCount; j++) {
1673
- const interiorRing = [];
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
- function readFirstPoint(reader, context) {
1697
- const x = zigZagDecode(reader.readVarInt()) / context.precisionFactor;
1698
- const y = zigZagDecode(reader.readVarInt()) / context.precisionFactor;
1699
- const z = context.hasZ ? zigZagDecode(reader.readVarInt()) / context.zPrecisionFactor : void 0;
1700
- const m = context.hasM ? zigZagDecode(reader.readVarInt()) / context.mPrecisionFactor : void 0;
1701
- return makePointCoordinates(x, y, z, m);
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 parseNextPoint(reader, context, previousPoint) {
1704
- previousPoint[0] += zigZagDecode(reader.readVarInt()) / context.precisionFactor;
1705
- previousPoint[1] += zigZagDecode(reader.readVarInt()) / context.precisionFactor;
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 (context.hasM) {
1710
- previousPoint[3] += zigZagDecode(reader.readVarInt()) / context.mPrecisionFactor;
1895
+ if (string.length < 10 || string.length % 2 !== 0) {
1896
+ return false;
1711
1897
  }
1712
- return previousPoint.slice();
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) => parseTWKBGeometry(arrayBuffer),
1739
- parseSync: parseTWKBGeometry
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
- encode: async (geometry, options) => encodeTWKB(geometry, options?.twkb),
1925
- encodeSync: (geometry, options) => encodeTWKB(geometry, options?.twkb),
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,