@math.gl/wkb 5.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +140 -0
- package/README.md +232 -0
- package/dist/index.cjs +947 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +34 -0
- package/dist/types.js.map +1 -0
- package/dist/wkb-builder.d.ts +87 -0
- package/dist/wkb-builder.d.ts.map +1 -0
- package/dist/wkb-builder.js +259 -0
- package/dist/wkb-builder.js.map +1 -0
- package/dist/wkb-reader.d.ts +74 -0
- package/dist/wkb-reader.d.ts.map +1 -0
- package/dist/wkb-reader.js +249 -0
- package/dist/wkb-reader.js.map +1 -0
- package/dist/wkb.d.ts +21 -0
- package/dist/wkb.d.ts.map +1 -0
- package/dist/wkb.js +204 -0
- package/dist/wkb.js.map +1 -0
- package/dist/wkt.d.ts +6 -0
- package/dist/wkt.d.ts.map +1 -0
- package/dist/wkt.js +224 -0
- package/dist/wkt.js.map +1 -0
- package/package.json +37 -0
- package/src/index.ts +37 -0
- package/src/types.ts +54 -0
- package/src/wkb-builder.ts +367 -0
- package/src/wkb-reader.ts +400 -0
- package/src/wkb.ts +253 -0
- package/src/wkt.ts +233 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
import { getWellKnownDimensionSize } from "./types.js";
|
|
5
|
+
const GEOMETRY_TYPES = [
|
|
6
|
+
'Point',
|
|
7
|
+
'LineString',
|
|
8
|
+
'Polygon',
|
|
9
|
+
'MultiPoint',
|
|
10
|
+
'MultiLineString',
|
|
11
|
+
'MultiPolygon',
|
|
12
|
+
'GeometryCollection'
|
|
13
|
+
];
|
|
14
|
+
/** Inspects one WKB/ISO WKB/EWKB header without reading its coordinate payload. */
|
|
15
|
+
export function inspectWKBHeader(input, byteOffset = 0) {
|
|
16
|
+
return inspectWKBHeaderView(getDataView(input), byteOffset);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Traverses exactly one WKB geometry without constructing coordinate or geometry objects.
|
|
20
|
+
* Returns the number of bytes consumed.
|
|
21
|
+
*/
|
|
22
|
+
export function visitWKB(input, visitor, options = {}) {
|
|
23
|
+
const view = getDataView(input);
|
|
24
|
+
const state = {
|
|
25
|
+
maximumDepth: validateLimit(options.maximumDepth, 64, 'maximumDepth'),
|
|
26
|
+
maximumElements: validateLimit(options.maximumElements, 100000000, 'maximumElements'),
|
|
27
|
+
elementCount: 0,
|
|
28
|
+
visitor
|
|
29
|
+
};
|
|
30
|
+
const byteLength = visitGeometry(view, 0, state, 0).byteOffset;
|
|
31
|
+
if (byteLength !== view.byteLength)
|
|
32
|
+
throw new Error('WKB contains trailing bytes');
|
|
33
|
+
return byteLength;
|
|
34
|
+
}
|
|
35
|
+
/** Collects geometry counts and XYZM bounds without materializing geometry rows. */
|
|
36
|
+
export function scanWKB(input, options = {}) {
|
|
37
|
+
const header = inspectWKBHeader(input);
|
|
38
|
+
const geometryCounts = {
|
|
39
|
+
Point: 0,
|
|
40
|
+
LineString: 0,
|
|
41
|
+
Polygon: 0,
|
|
42
|
+
MultiPoint: 0,
|
|
43
|
+
MultiLineString: 0,
|
|
44
|
+
MultiPolygon: 0,
|
|
45
|
+
GeometryCollection: 0
|
|
46
|
+
};
|
|
47
|
+
const geometryTypes = new Set();
|
|
48
|
+
const bounds = {};
|
|
49
|
+
let coordinateCount = 0;
|
|
50
|
+
let ringCount = 0;
|
|
51
|
+
let geometryCount = 0;
|
|
52
|
+
let maximumDepth = 0;
|
|
53
|
+
const byteLength = visitWKB(input, {
|
|
54
|
+
geometry: (geometryHeader, _count, depth) => {
|
|
55
|
+
geometryCounts[geometryHeader.geometryType]++;
|
|
56
|
+
geometryTypes.add(geometryHeader.geometryType);
|
|
57
|
+
geometryCount++;
|
|
58
|
+
maximumDepth = Math.max(maximumDepth, depth);
|
|
59
|
+
},
|
|
60
|
+
ring: () => ringCount++,
|
|
61
|
+
coordinate: (x, y, z, m) => {
|
|
62
|
+
coordinateCount++;
|
|
63
|
+
updateBounds(bounds, 'x', x);
|
|
64
|
+
updateBounds(bounds, 'y', y);
|
|
65
|
+
if (z !== undefined)
|
|
66
|
+
updateBounds(bounds, 'z', z);
|
|
67
|
+
if (m !== undefined)
|
|
68
|
+
updateBounds(bounds, 'm', m);
|
|
69
|
+
}
|
|
70
|
+
}, options);
|
|
71
|
+
const concreteBounds = makeBounds(bounds);
|
|
72
|
+
return {
|
|
73
|
+
header,
|
|
74
|
+
byteLength,
|
|
75
|
+
coordinateCount,
|
|
76
|
+
ringCount,
|
|
77
|
+
geometryCount,
|
|
78
|
+
maximumDepth,
|
|
79
|
+
geometryTypes: GEOMETRY_TYPES.filter(type => geometryTypes.has(type)),
|
|
80
|
+
geometryCounts,
|
|
81
|
+
...(concreteBounds ? { bounds: concreteBounds } : {})
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function visitGeometry(view, byteOffset, state, depth, expectedType) {
|
|
85
|
+
if (depth > state.maximumDepth)
|
|
86
|
+
throw new Error('WKB geometry nesting exceeds maximumDepth');
|
|
87
|
+
const header = inspectWKBHeaderView(view, byteOffset);
|
|
88
|
+
if (expectedType && header.geometryType !== expectedType) {
|
|
89
|
+
throw new Error(`WKB ${expectedType} collection contains a ${header.geometryType} child`);
|
|
90
|
+
}
|
|
91
|
+
byteOffset = header.bodyByteOffset;
|
|
92
|
+
switch (header.geometryType) {
|
|
93
|
+
case 'Point':
|
|
94
|
+
state.visitor.geometry?.(header, undefined, depth);
|
|
95
|
+
byteOffset = visitCoordinate(view, byteOffset, header, state.visitor, depth);
|
|
96
|
+
break;
|
|
97
|
+
case 'LineString': {
|
|
98
|
+
const pointCount = readCount(view, byteOffset, header.littleEndian, state);
|
|
99
|
+
byteOffset += 4;
|
|
100
|
+
state.visitor.geometry?.(header, pointCount, depth);
|
|
101
|
+
byteOffset = visitCoordinateSequence(view, byteOffset, pointCount, header, state, depth);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'Polygon': {
|
|
105
|
+
const ringCount = readCount(view, byteOffset, header.littleEndian, state);
|
|
106
|
+
byteOffset += 4;
|
|
107
|
+
state.visitor.geometry?.(header, ringCount, depth);
|
|
108
|
+
for (let ringIndex = 0; ringIndex < ringCount; ringIndex++) {
|
|
109
|
+
const pointCount = readCount(view, byteOffset, header.littleEndian, state);
|
|
110
|
+
byteOffset += 4;
|
|
111
|
+
state.visitor.ring?.(pointCount, ringIndex, depth);
|
|
112
|
+
byteOffset = visitCoordinateSequence(view, byteOffset, pointCount, header, state, depth);
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'MultiPoint':
|
|
117
|
+
case 'MultiLineString':
|
|
118
|
+
case 'MultiPolygon':
|
|
119
|
+
case 'GeometryCollection': {
|
|
120
|
+
const childCount = readCount(view, byteOffset, header.littleEndian, state);
|
|
121
|
+
byteOffset += 4;
|
|
122
|
+
state.visitor.geometry?.(header, childCount, depth);
|
|
123
|
+
const childType = header.geometryType === 'MultiPoint'
|
|
124
|
+
? 'Point'
|
|
125
|
+
: header.geometryType === 'MultiLineString'
|
|
126
|
+
? 'LineString'
|
|
127
|
+
: header.geometryType === 'MultiPolygon'
|
|
128
|
+
? 'Polygon'
|
|
129
|
+
: undefined;
|
|
130
|
+
for (let childIndex = 0; childIndex < childCount; childIndex++) {
|
|
131
|
+
byteOffset = visitGeometry(view, byteOffset, state, depth + 1, childType).byteOffset;
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { byteOffset, header };
|
|
137
|
+
}
|
|
138
|
+
function visitCoordinateSequence(view, byteOffset, pointCount, header, state, depth) {
|
|
139
|
+
for (let pointIndex = 0; pointIndex < pointCount; pointIndex++) {
|
|
140
|
+
byteOffset = visitCoordinate(view, byteOffset, header, state.visitor, depth);
|
|
141
|
+
}
|
|
142
|
+
return byteOffset;
|
|
143
|
+
}
|
|
144
|
+
function visitCoordinate(view, byteOffset, header, visitor, depth) {
|
|
145
|
+
const coordinateByteLength = getWellKnownDimensionSize(header.dimension) * 8;
|
|
146
|
+
assertRemaining(view, byteOffset, coordinateByteLength);
|
|
147
|
+
const x = view.getFloat64(byteOffset, header.littleEndian);
|
|
148
|
+
const y = view.getFloat64(byteOffset + 8, header.littleEndian);
|
|
149
|
+
const third = header.dimension === 'xy' ? undefined : view.getFloat64(byteOffset + 16, header.littleEndian);
|
|
150
|
+
const fourth = header.dimension === 'xyzm' ? view.getFloat64(byteOffset + 24, header.littleEndian) : undefined;
|
|
151
|
+
const z = header.dimension === 'xyz' || header.dimension === 'xyzm' ? third : undefined;
|
|
152
|
+
const m = header.dimension === 'xym' ? third : fourth;
|
|
153
|
+
visitor.coordinate?.(x, y, z, m, header.dimension, byteOffset, depth);
|
|
154
|
+
return byteOffset + coordinateByteLength;
|
|
155
|
+
}
|
|
156
|
+
function inspectWKBHeaderView(view, byteOffset) {
|
|
157
|
+
const startByteOffset = byteOffset;
|
|
158
|
+
assertRemaining(view, byteOffset, 5);
|
|
159
|
+
const byteOrder = view.getUint8(byteOffset++);
|
|
160
|
+
if (byteOrder !== 0 && byteOrder !== 1)
|
|
161
|
+
throw new Error('Invalid WKB byte order');
|
|
162
|
+
const littleEndian = byteOrder === 1;
|
|
163
|
+
const typeCode = view.getUint32(byteOffset, littleEndian);
|
|
164
|
+
byteOffset += 4;
|
|
165
|
+
const hasZ = Boolean(typeCode & 0x80000000);
|
|
166
|
+
const hasM = Boolean(typeCode & 0x40000000);
|
|
167
|
+
const hasSrid = Boolean(typeCode & 0x20000000);
|
|
168
|
+
let geometryCode = typeCode & 0x1fffffff;
|
|
169
|
+
let dimension;
|
|
170
|
+
if (geometryCode >= 3000 && geometryCode < 4000) {
|
|
171
|
+
dimension = 'xyzm';
|
|
172
|
+
geometryCode -= 3000;
|
|
173
|
+
}
|
|
174
|
+
else if (geometryCode >= 2000 && geometryCode < 3000) {
|
|
175
|
+
dimension = 'xym';
|
|
176
|
+
geometryCode -= 2000;
|
|
177
|
+
}
|
|
178
|
+
else if (geometryCode >= 1000 && geometryCode < 2000) {
|
|
179
|
+
dimension = 'xyz';
|
|
180
|
+
geometryCode -= 1000;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
dimension = hasZ && hasM ? 'xyzm' : hasZ ? 'xyz' : hasM ? 'xym' : 'xy';
|
|
184
|
+
}
|
|
185
|
+
const geometryType = GEOMETRY_TYPES[geometryCode - 1];
|
|
186
|
+
if (!geometryType)
|
|
187
|
+
throw new Error(`Unsupported WKB geometry type ${geometryCode}`);
|
|
188
|
+
let srid;
|
|
189
|
+
if (hasSrid) {
|
|
190
|
+
assertRemaining(view, byteOffset, 4);
|
|
191
|
+
srid = view.getUint32(byteOffset, littleEndian);
|
|
192
|
+
byteOffset += 4;
|
|
193
|
+
}
|
|
194
|
+
const dialect = hasZ || hasM || hasSrid ? 'ewkb' : dimension === 'xy' ? 'wkb' : 'iso-wkb';
|
|
195
|
+
return {
|
|
196
|
+
geometryType,
|
|
197
|
+
dimension,
|
|
198
|
+
dialect,
|
|
199
|
+
littleEndian,
|
|
200
|
+
byteOffset: startByteOffset,
|
|
201
|
+
bodyByteOffset: byteOffset,
|
|
202
|
+
byteLength: byteOffset - startByteOffset,
|
|
203
|
+
...(srid === undefined ? {} : { srid })
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function readCount(view, byteOffset, littleEndian, state) {
|
|
207
|
+
assertRemaining(view, byteOffset, 4);
|
|
208
|
+
const count = view.getUint32(byteOffset, littleEndian);
|
|
209
|
+
state.elementCount += count;
|
|
210
|
+
if (state.elementCount > state.maximumElements) {
|
|
211
|
+
throw new Error('WKB element count exceeds maximumElements');
|
|
212
|
+
}
|
|
213
|
+
return count;
|
|
214
|
+
}
|
|
215
|
+
function updateBounds(bounds, axis, value) {
|
|
216
|
+
if (!Number.isFinite(value))
|
|
217
|
+
return;
|
|
218
|
+
const minimum = `${axis}min`;
|
|
219
|
+
const maximum = `${axis}max`;
|
|
220
|
+
bounds[minimum] = bounds[minimum] === undefined ? value : Math.min(bounds[minimum], value);
|
|
221
|
+
bounds[maximum] = bounds[maximum] === undefined ? value : Math.max(bounds[maximum], value);
|
|
222
|
+
}
|
|
223
|
+
function makeBounds(bounds) {
|
|
224
|
+
if (bounds.xmin === undefined ||
|
|
225
|
+
bounds.ymin === undefined ||
|
|
226
|
+
bounds.xmax === undefined ||
|
|
227
|
+
bounds.ymax === undefined) {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
return bounds;
|
|
231
|
+
}
|
|
232
|
+
function getDataView(input) {
|
|
233
|
+
return ArrayBuffer.isView(input)
|
|
234
|
+
? new DataView(input.buffer, input.byteOffset, input.byteLength)
|
|
235
|
+
: new DataView(input);
|
|
236
|
+
}
|
|
237
|
+
function assertRemaining(view, byteOffset, byteLength) {
|
|
238
|
+
if (byteOffset < 0 || byteOffset + byteLength > view.byteLength) {
|
|
239
|
+
throw new Error('Unexpected end of WKB');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function validateLimit(value, fallback, name) {
|
|
243
|
+
const limit = value ?? fallback;
|
|
244
|
+
if (!Number.isSafeInteger(limit) || limit < 0) {
|
|
245
|
+
throw new Error(`${name} must be a non-negative safe integer`);
|
|
246
|
+
}
|
|
247
|
+
return limit;
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=wkb-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wkb-reader.js","sourceRoot":"","sources":["../src/wkb-reader.ts"],"names":[],"mappings":"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"}
|
package/dist/wkb.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WellKnownDimension, WellKnownGeometry } from "./types.js";
|
|
2
|
+
/** Defensive limits applied before WKB allocates geometry arrays. */
|
|
3
|
+
export type WKBParseOptions = Readonly<{
|
|
4
|
+
/** Maximum recursive geometry nesting. Defaults to 64. */
|
|
5
|
+
maximumDepth?: number;
|
|
6
|
+
/** Maximum total declared child elements. Defaults to 100 million. */
|
|
7
|
+
maximumElements?: number;
|
|
8
|
+
}>;
|
|
9
|
+
/** One completely parsed WKB value and metadata declared by its root header. */
|
|
10
|
+
export type WKBParseResult = Readonly<{
|
|
11
|
+
geometry: WellKnownGeometry;
|
|
12
|
+
byteLength: number;
|
|
13
|
+
dimension: WellKnownDimension;
|
|
14
|
+
/** EWKB SRID when the root header carries one. */
|
|
15
|
+
srid?: number;
|
|
16
|
+
}>;
|
|
17
|
+
/** Parses exactly one little- or big-endian ISO WKB or EWKB geometry. */
|
|
18
|
+
export declare function parseWKB(bytes: Uint8Array, options?: WKBParseOptions): WKBParseResult;
|
|
19
|
+
/** Writes one geometry as little-endian ISO WKB. */
|
|
20
|
+
export declare function writeWKB(geometry: WellKnownGeometry, dimension?: WellKnownDimension): Uint8Array;
|
|
21
|
+
//# sourceMappingURL=wkb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wkb.d.ts","sourceRoot":"","sources":["../src/wkb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAE,iBAAiB,EAAC,mBAAgB;AAInE,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC,CAAC;AAEH,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAeH,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CAezF;AAED,oDAAoD;AACpD,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,GAAE,kBAA8D,GACxE,UAAU,CAIZ"}
|
package/dist/wkb.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
import { getWellKnownDimensionSize, inferWellKnownGeometryDimension } from "./types.js";
|
|
5
|
+
import { inspectWKBHeader } from "./wkb-reader.js";
|
|
6
|
+
/** Parses exactly one little- or big-endian ISO WKB or EWKB geometry. */
|
|
7
|
+
export function parseWKB(bytes, options = {}) {
|
|
8
|
+
const state = {
|
|
9
|
+
maximumDepth: validateLimit(options.maximumDepth, 64, 'maximumDepth'),
|
|
10
|
+
maximumElements: validateLimit(options.maximumElements, 100000000, 'maximumElements'),
|
|
11
|
+
elementCount: 0
|
|
12
|
+
};
|
|
13
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
14
|
+
const result = readWKBGeometry(view, 0, state, 0);
|
|
15
|
+
if (result.offset !== bytes.byteLength)
|
|
16
|
+
throw new Error('WKB contains trailing bytes');
|
|
17
|
+
return {
|
|
18
|
+
geometry: result.geometry,
|
|
19
|
+
byteLength: result.offset,
|
|
20
|
+
dimension: result.dimension,
|
|
21
|
+
...(result.srid === undefined ? {} : { srid: result.srid })
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Writes one geometry as little-endian ISO WKB. */
|
|
25
|
+
export function writeWKB(geometry, dimension = inferWellKnownGeometryDimension(geometry)) {
|
|
26
|
+
const bytes = [];
|
|
27
|
+
writeWKBGeometry(bytes, geometry, dimension);
|
|
28
|
+
return Uint8Array.from(bytes);
|
|
29
|
+
}
|
|
30
|
+
function readWKBGeometry(view, startOffset, state, depth) {
|
|
31
|
+
if (depth > state.maximumDepth)
|
|
32
|
+
throw new Error('WKB geometry nesting exceeds maximumDepth');
|
|
33
|
+
const header = inspectWKBHeader(view, startOffset);
|
|
34
|
+
let offset = header.bodyByteOffset;
|
|
35
|
+
const { dimension, geometryType, littleEndian, srid } = header;
|
|
36
|
+
const dimensions = getWellKnownDimensionSize(dimension);
|
|
37
|
+
const readCoordinate = () => {
|
|
38
|
+
assertRemaining(view, offset, dimensions * 8);
|
|
39
|
+
const coordinate = new Array(dimensions);
|
|
40
|
+
for (let index = 0; index < dimensions; index++) {
|
|
41
|
+
coordinate[index] = view.getFloat64(offset, littleEndian);
|
|
42
|
+
offset += 8;
|
|
43
|
+
}
|
|
44
|
+
return coordinate;
|
|
45
|
+
};
|
|
46
|
+
const readCount = () => {
|
|
47
|
+
assertRemaining(view, offset, 4);
|
|
48
|
+
const count = view.getUint32(offset, littleEndian);
|
|
49
|
+
offset += 4;
|
|
50
|
+
state.elementCount += count;
|
|
51
|
+
if (state.elementCount > state.maximumElements) {
|
|
52
|
+
throw new Error('WKB element count exceeds maximumElements');
|
|
53
|
+
}
|
|
54
|
+
return count;
|
|
55
|
+
};
|
|
56
|
+
const readCoordinates = () => {
|
|
57
|
+
const count = readCount();
|
|
58
|
+
return Array.from({ length: count }, readCoordinate);
|
|
59
|
+
};
|
|
60
|
+
let geometry;
|
|
61
|
+
switch (geometryType) {
|
|
62
|
+
case 'Point':
|
|
63
|
+
geometry = { type: 'Point', coordinates: readCoordinate() };
|
|
64
|
+
break;
|
|
65
|
+
case 'LineString':
|
|
66
|
+
geometry = { type: 'LineString', coordinates: readCoordinates() };
|
|
67
|
+
break;
|
|
68
|
+
case 'Polygon':
|
|
69
|
+
geometry = { type: 'Polygon', coordinates: Array.from({ length: readCount() }, readCoordinates) };
|
|
70
|
+
break;
|
|
71
|
+
case 'MultiPoint':
|
|
72
|
+
case 'MultiLineString':
|
|
73
|
+
case 'MultiPolygon':
|
|
74
|
+
case 'GeometryCollection': {
|
|
75
|
+
const children = [];
|
|
76
|
+
for (let index = 0, count = readCount(); index < count; index++) {
|
|
77
|
+
const child = readWKBGeometry(view, offset, state, depth + 1);
|
|
78
|
+
children.push(child.geometry);
|
|
79
|
+
offset = child.offset;
|
|
80
|
+
}
|
|
81
|
+
if (geometryType === 'MultiPoint') {
|
|
82
|
+
geometry = {
|
|
83
|
+
type: 'MultiPoint',
|
|
84
|
+
coordinates: children.map(assertPoint).map(point => point.coordinates)
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
else if (geometryType === 'MultiLineString') {
|
|
88
|
+
geometry = {
|
|
89
|
+
type: 'MultiLineString',
|
|
90
|
+
coordinates: children.map(assertLineString).map(line => line.coordinates)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
else if (geometryType === 'MultiPolygon') {
|
|
94
|
+
geometry = {
|
|
95
|
+
type: 'MultiPolygon',
|
|
96
|
+
coordinates: children.map(assertPolygon).map(polygon => polygon.coordinates)
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
geometry = { type: 'GeometryCollection', geometries: children };
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return { geometry, offset, dimension, ...(srid === undefined ? {} : { srid }) };
|
|
106
|
+
}
|
|
107
|
+
function writeWKBGeometry(bytes, geometry, dimension) {
|
|
108
|
+
bytes.push(1);
|
|
109
|
+
const size = getWellKnownDimensionSize(dimension);
|
|
110
|
+
const dimensionOffset = dimension === 'xyz' ? 1000 : dimension === 'xym' ? 2000 : dimension === 'xyzm' ? 3000 : 0;
|
|
111
|
+
writeUint32(bytes, getWKBType(geometry.type) + dimensionOffset);
|
|
112
|
+
const writeCoordinate = (coordinate) => {
|
|
113
|
+
for (let index = 0; index < size; index++)
|
|
114
|
+
writeFloat64(bytes, coordinate[index] ?? 0);
|
|
115
|
+
};
|
|
116
|
+
const writeCoordinates = (coordinates) => {
|
|
117
|
+
writeUint32(bytes, coordinates.length);
|
|
118
|
+
for (const coordinate of coordinates)
|
|
119
|
+
writeCoordinate(coordinate);
|
|
120
|
+
};
|
|
121
|
+
switch (geometry.type) {
|
|
122
|
+
case 'Point':
|
|
123
|
+
writeCoordinate(geometry.coordinates);
|
|
124
|
+
break;
|
|
125
|
+
case 'LineString':
|
|
126
|
+
writeCoordinates(geometry.coordinates);
|
|
127
|
+
break;
|
|
128
|
+
case 'Polygon':
|
|
129
|
+
writeUint32(bytes, geometry.coordinates.length);
|
|
130
|
+
for (const ring of geometry.coordinates)
|
|
131
|
+
writeCoordinates(ring);
|
|
132
|
+
break;
|
|
133
|
+
case 'MultiPoint':
|
|
134
|
+
writeUint32(bytes, geometry.coordinates.length);
|
|
135
|
+
for (const coordinate of geometry.coordinates) {
|
|
136
|
+
writeWKBGeometry(bytes, { type: 'Point', coordinates: coordinate }, dimension);
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case 'MultiLineString':
|
|
140
|
+
writeUint32(bytes, geometry.coordinates.length);
|
|
141
|
+
for (const coordinates of geometry.coordinates) {
|
|
142
|
+
writeWKBGeometry(bytes, { type: 'LineString', coordinates }, dimension);
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
case 'MultiPolygon':
|
|
146
|
+
writeUint32(bytes, geometry.coordinates.length);
|
|
147
|
+
for (const coordinates of geometry.coordinates) {
|
|
148
|
+
writeWKBGeometry(bytes, { type: 'Polygon', coordinates }, dimension);
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
case 'GeometryCollection':
|
|
152
|
+
writeUint32(bytes, geometry.geometries.length);
|
|
153
|
+
for (const child of geometry.geometries)
|
|
154
|
+
writeWKBGeometry(bytes, child, dimension);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function getWKBType(type) {
|
|
159
|
+
return ([
|
|
160
|
+
'Point',
|
|
161
|
+
'LineString',
|
|
162
|
+
'Polygon',
|
|
163
|
+
'MultiPoint',
|
|
164
|
+
'MultiLineString',
|
|
165
|
+
'MultiPolygon',
|
|
166
|
+
'GeometryCollection'
|
|
167
|
+
].indexOf(type) + 1);
|
|
168
|
+
}
|
|
169
|
+
function writeUint32(bytes, value) {
|
|
170
|
+
bytes.push(value & 255, (value >>> 8) & 255, (value >>> 16) & 255, (value >>> 24) & 255);
|
|
171
|
+
}
|
|
172
|
+
function writeFloat64(bytes, value) {
|
|
173
|
+
const buffer = new ArrayBuffer(8);
|
|
174
|
+
new DataView(buffer).setFloat64(0, value, true);
|
|
175
|
+
bytes.push(...new Uint8Array(buffer));
|
|
176
|
+
}
|
|
177
|
+
function assertRemaining(view, offset, length) {
|
|
178
|
+
if (offset + length > view.byteLength)
|
|
179
|
+
throw new Error('Unexpected end of WKB');
|
|
180
|
+
}
|
|
181
|
+
function assertPoint(value) {
|
|
182
|
+
if (value.type !== 'Point')
|
|
183
|
+
throw new Error('WKB MultiPoint contains a non-Point child');
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
function assertLineString(value) {
|
|
187
|
+
if (value.type !== 'LineString') {
|
|
188
|
+
throw new Error('WKB MultiLineString contains a non-LineString child');
|
|
189
|
+
}
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
function assertPolygon(value) {
|
|
193
|
+
if (value.type !== 'Polygon')
|
|
194
|
+
throw new Error('WKB MultiPolygon contains a non-Polygon child');
|
|
195
|
+
return value;
|
|
196
|
+
}
|
|
197
|
+
function validateLimit(value, fallback, name) {
|
|
198
|
+
const limit = value ?? fallback;
|
|
199
|
+
if (!Number.isSafeInteger(limit) || limit < 0) {
|
|
200
|
+
throw new Error(`${name} must be a non-negative safe integer`);
|
|
201
|
+
}
|
|
202
|
+
return limit;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=wkb.js.map
|
package/dist/wkb.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wkb.js","sourceRoot":"","sources":["../src/wkb.ts"],"names":[],"mappings":"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"}
|
package/dist/wkt.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WellKnownDimension, WellKnownGeometry } from "./types.js";
|
|
2
|
+
/** Parses one WKT geometry, including Z/M/ZM, collections, alternate MultiPoint, and empties. */
|
|
3
|
+
export declare function parseWKT(text: string): WellKnownGeometry;
|
|
4
|
+
/** Formats one geometry as WKT using an explicit or tuple-inferred semantic dimension. */
|
|
5
|
+
export declare function formatWKT(geometry: WellKnownGeometry, dimension?: WellKnownDimension): string;
|
|
6
|
+
//# sourceMappingURL=wkt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wkt.d.ts","sourceRoot":"","sources":["../src/wkt.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAE,iBAAiB,EAAC,mBAAgB;AAGnE,iGAAiG;AACjG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAKxD;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CACvB,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,GAAE,kBAA8D,GACxE,MAAM,CASR"}
|