@math.gl/geoarrow 5.0.0-alpha.2 → 5.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -15
- package/dist/builder-entry.cjs +561 -0
- package/dist/builder-entry.cjs.map +6 -0
- package/dist/builder-entry.d.ts +4 -0
- package/dist/builder-entry.d.ts.map +1 -0
- package/dist/builder-entry.js +5 -0
- package/dist/builder-entry.js.map +1 -0
- package/dist/builder.d.ts +12 -1
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +112 -10
- package/dist/builder.js.map +1 -1
- package/dist/codecs.d.ts.map +1 -1
- package/dist/codecs.js +205 -7
- package/dist/codecs.js.map +1 -1
- package/dist/index.cjs +904 -120
- package/dist/index.cjs.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kernels.d.ts +8 -3
- package/dist/kernels.d.ts.map +1 -1
- package/dist/kernels.js +610 -107
- package/dist/kernels.js.map +1 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +28 -5
- package/dist/layout.js.map +1 -1
- package/dist/tessellation-entry.cjs +427 -0
- package/dist/tessellation-entry.cjs.map +6 -0
- package/dist/tessellation-entry.d.ts +4 -0
- package/dist/tessellation-entry.d.ts.map +1 -0
- package/dist/tessellation-entry.js +5 -0
- package/dist/tessellation-entry.js.map +1 -0
- package/dist/types.d.ts +37 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wkb-entry.cjs +1005 -0
- package/dist/wkb-entry.cjs.map +6 -0
- package/dist/wkb-entry.d.ts +3 -0
- package/dist/wkb-entry.d.ts.map +1 -0
- package/dist/wkb-entry.js +6 -0
- package/dist/wkb-entry.js.map +1 -0
- package/dist/worker.cjs +4 -0
- package/dist/worker.cjs.map +1 -1
- package/package.json +21 -6
- package/src/builder-entry.ts +18 -0
- package/src/builder.ts +133 -19
- package/src/codecs.ts +251 -9
- package/src/index.ts +1 -0
- package/src/kernels.ts +811 -133
- package/src/layout.ts +38 -13
- package/src/tessellation-entry.ts +7 -0
- package/src/types.ts +23 -4
- package/src/wkb-entry.ts +11 -0
|
@@ -0,0 +1,1005 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// dist/wkb-entry.js
|
|
20
|
+
var wkb_entry_exports = {};
|
|
21
|
+
__export(wkb_entry_exports, {
|
|
22
|
+
decodeGeoArrowWKB: () => decodeGeoArrowWKB,
|
|
23
|
+
decodeGeoArrowWKT: () => decodeGeoArrowWKT,
|
|
24
|
+
encodeGeoArrowWKB: () => encodeGeoArrowWKB,
|
|
25
|
+
encodeGeoArrowWKT: () => encodeGeoArrowWKT
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(wkb_entry_exports);
|
|
28
|
+
|
|
29
|
+
// dist/codecs.js
|
|
30
|
+
var import_wkb = require("@math.gl/wkb");
|
|
31
|
+
var import_wkb2 = require("@math.gl/wkb");
|
|
32
|
+
|
|
33
|
+
// dist/types.js
|
|
34
|
+
function getGeoArrowDimensionSize(dimension) {
|
|
35
|
+
switch (dimension) {
|
|
36
|
+
case "xy":
|
|
37
|
+
return 2;
|
|
38
|
+
case "xyz":
|
|
39
|
+
case "xym":
|
|
40
|
+
return 3;
|
|
41
|
+
case "xyzm":
|
|
42
|
+
return 4;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function getGeoArrowGeometryType(encoding) {
|
|
46
|
+
switch (encoding) {
|
|
47
|
+
case "geoarrow.point":
|
|
48
|
+
return "Point";
|
|
49
|
+
case "geoarrow.linestring":
|
|
50
|
+
return "LineString";
|
|
51
|
+
case "geoarrow.polygon":
|
|
52
|
+
return "Polygon";
|
|
53
|
+
case "geoarrow.multipoint":
|
|
54
|
+
return "MultiPoint";
|
|
55
|
+
case "geoarrow.multilinestring":
|
|
56
|
+
return "MultiLineString";
|
|
57
|
+
case "geoarrow.multipolygon":
|
|
58
|
+
return "MultiPolygon";
|
|
59
|
+
case "geoarrow.geometrycollection":
|
|
60
|
+
return "GeometryCollection";
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function getGeoArrowEncodingForGeometry(type) {
|
|
66
|
+
return `geoarrow.${type.toLowerCase()}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// dist/builder.js
|
|
70
|
+
var GeoArrowBuilder = class _GeoArrowBuilder {
|
|
71
|
+
constructor(options) {
|
|
72
|
+
this.length = 0;
|
|
73
|
+
this.nullCount = 0;
|
|
74
|
+
this.coordinateCount = 0;
|
|
75
|
+
this.partCount = 0;
|
|
76
|
+
this.ringCount = 0;
|
|
77
|
+
this.eventStack = [];
|
|
78
|
+
this.mode = options.mode;
|
|
79
|
+
this.encoding = options.encoding;
|
|
80
|
+
this.dimension = options.dimension || "xy";
|
|
81
|
+
this.coordinateLayout = options.coordinateLayout || "interleaved";
|
|
82
|
+
this.offsetType = options.offsetType || "int32";
|
|
83
|
+
this.coordinateType = options.coordinateType || "float64";
|
|
84
|
+
this.target = options.mode === "write" ? options.target : void 0;
|
|
85
|
+
if (this.target)
|
|
86
|
+
this.initializeTargetOffsets(this.target);
|
|
87
|
+
}
|
|
88
|
+
/** Appends one geometry row or null. */
|
|
89
|
+
append(geometry) {
|
|
90
|
+
var _a, _b, _c, _d, _e, _f;
|
|
91
|
+
const rowIndex = this.length++;
|
|
92
|
+
if (!geometry) {
|
|
93
|
+
this.nullCount++;
|
|
94
|
+
this.appendNull(rowIndex);
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
const expectedType = getGeoArrowGeometryType(this.encoding);
|
|
98
|
+
if (geometry.type !== expectedType) {
|
|
99
|
+
throw new Error(`GeoArrowBuilder for ${this.encoding} cannot append ${geometry.type}`);
|
|
100
|
+
}
|
|
101
|
+
if (geometry.type === "GeometryCollection") {
|
|
102
|
+
throw new Error("GeoArrowBuilder only accepts concrete geometry families");
|
|
103
|
+
}
|
|
104
|
+
if (this.target)
|
|
105
|
+
setValidityBit(this.target.validity, rowIndex);
|
|
106
|
+
const depth = getBuilderDepth(this.encoding);
|
|
107
|
+
const coordinates = geometry.coordinates;
|
|
108
|
+
if (depth === 0) {
|
|
109
|
+
this.writeCoordinateValues(coordinates);
|
|
110
|
+
} else if (depth === 1) {
|
|
111
|
+
this.writeCoordinateList(coordinates);
|
|
112
|
+
this.writeOffset((_a = this.target) == null ? void 0 : _a.geometryOffsets, rowIndex + 1, this.coordinateCount);
|
|
113
|
+
} else if (depth === 2) {
|
|
114
|
+
for (const part of coordinates) {
|
|
115
|
+
this.writeCoordinateList(part);
|
|
116
|
+
this.partCount++;
|
|
117
|
+
this.writeOffset((_b = this.target) == null ? void 0 : _b.partOffsets, this.partCount, this.coordinateCount);
|
|
118
|
+
}
|
|
119
|
+
this.writeOffset((_c = this.target) == null ? void 0 : _c.geometryOffsets, rowIndex + 1, this.partCount);
|
|
120
|
+
} else {
|
|
121
|
+
for (const polygon of coordinates) {
|
|
122
|
+
for (const ring of polygon) {
|
|
123
|
+
this.writeCoordinateList(ring);
|
|
124
|
+
this.ringCount++;
|
|
125
|
+
this.writeOffset((_d = this.target) == null ? void 0 : _d.ringOffsets, this.ringCount, this.coordinateCount);
|
|
126
|
+
}
|
|
127
|
+
this.partCount++;
|
|
128
|
+
this.writeOffset((_e = this.target) == null ? void 0 : _e.partOffsets, this.partCount, this.ringCount);
|
|
129
|
+
}
|
|
130
|
+
this.writeOffset((_f = this.target) == null ? void 0 : _f.geometryOffsets, rowIndex + 1, this.partCount);
|
|
131
|
+
}
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
/** Returns current exact allocation counts. */
|
|
135
|
+
getMeasurement() {
|
|
136
|
+
const depth = getBuilderDepth(this.encoding);
|
|
137
|
+
return {
|
|
138
|
+
length: this.length,
|
|
139
|
+
nullCount: this.nullCount,
|
|
140
|
+
coordinateCount: this.coordinateCount,
|
|
141
|
+
geometryOffsetCount: depth >= 1 ? this.length + 1 : 0,
|
|
142
|
+
partOffsetCount: depth >= 2 ? this.partCount + 1 : 0,
|
|
143
|
+
ringOffsetCount: depth >= 3 ? this.ringCount + 1 : 0
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/** Allocates a write target from the current measure pass. */
|
|
147
|
+
allocateTarget() {
|
|
148
|
+
if (this.mode !== "measure")
|
|
149
|
+
throw new Error("Only a measure builder can allocate a target");
|
|
150
|
+
return allocateGeoArrowBuilderTarget(this.getMeasurement(), {
|
|
151
|
+
encoding: this.encoding,
|
|
152
|
+
dimension: this.dimension,
|
|
153
|
+
coordinateLayout: this.coordinateLayout,
|
|
154
|
+
offsetType: this.offsetType,
|
|
155
|
+
coordinateType: this.coordinateType
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/** Finishes a write pass and returns a one-chunk borrowed column. */
|
|
159
|
+
finish() {
|
|
160
|
+
if (!this.target)
|
|
161
|
+
throw new Error("A measure builder has no finished column");
|
|
162
|
+
const measurement = this.getMeasurement();
|
|
163
|
+
assertTargetCapacity(this.target, measurement, getGeoArrowDimensionSize(this.dimension));
|
|
164
|
+
const coordinates = makeCoordinateArray(this.target.coordinates, measurement.coordinateCount, this.dimension, this.coordinateLayout);
|
|
165
|
+
const depth = getBuilderDepth(this.encoding);
|
|
166
|
+
let chunk = coordinates;
|
|
167
|
+
if (depth >= 3) {
|
|
168
|
+
chunk = {
|
|
169
|
+
kind: "list",
|
|
170
|
+
length: this.ringCount,
|
|
171
|
+
offsets: this.target.ringOffsets,
|
|
172
|
+
child: chunk
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (depth >= 2) {
|
|
176
|
+
chunk = {
|
|
177
|
+
kind: "list",
|
|
178
|
+
length: this.partCount,
|
|
179
|
+
offsets: this.target.partOffsets,
|
|
180
|
+
child: chunk
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (depth >= 1) {
|
|
184
|
+
chunk = {
|
|
185
|
+
kind: "list",
|
|
186
|
+
length: this.length,
|
|
187
|
+
offsets: this.target.geometryOffsets,
|
|
188
|
+
child: chunk,
|
|
189
|
+
validity: { values: this.target.validity }
|
|
190
|
+
};
|
|
191
|
+
} else {
|
|
192
|
+
chunk = { ...chunk, validity: { values: this.target.validity } };
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
encoding: this.encoding,
|
|
196
|
+
dimension: this.dimension,
|
|
197
|
+
coordinateLayout: this.coordinateLayout,
|
|
198
|
+
chunks: [chunk]
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/** Builds a homogeneous column using an internal measure/write pair. */
|
|
202
|
+
static build(rows, options) {
|
|
203
|
+
const measure = new _GeoArrowBuilder({ ...options, mode: "measure" });
|
|
204
|
+
for (const row of rows)
|
|
205
|
+
measure.append(row);
|
|
206
|
+
const write = new _GeoArrowBuilder({
|
|
207
|
+
...options,
|
|
208
|
+
mode: "write",
|
|
209
|
+
target: measure.allocateTarget()
|
|
210
|
+
});
|
|
211
|
+
for (const row of rows)
|
|
212
|
+
write.append(row);
|
|
213
|
+
return write.finish();
|
|
214
|
+
}
|
|
215
|
+
appendNull(rowIndex) {
|
|
216
|
+
var _a;
|
|
217
|
+
const depth = getBuilderDepth(this.encoding);
|
|
218
|
+
if (depth === 0) {
|
|
219
|
+
this.writeCoordinateValues(new Array(getGeoArrowDimensionSize(this.dimension)).fill(0));
|
|
220
|
+
} else {
|
|
221
|
+
this.writeOffset((_a = this.target) == null ? void 0 : _a.geometryOffsets, rowIndex + 1, depth === 1 ? this.coordinateCount : this.partCount);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
writeCoordinateList(coordinates) {
|
|
225
|
+
for (const coordinate of coordinates)
|
|
226
|
+
this.writeCoordinateValues(coordinate);
|
|
227
|
+
}
|
|
228
|
+
writeCoordinateValues(coordinate) {
|
|
229
|
+
const size = getGeoArrowDimensionSize(this.dimension);
|
|
230
|
+
if (coordinate.length !== size) {
|
|
231
|
+
throw new Error(`Expected ${size} coordinate values for ${this.dimension}`);
|
|
232
|
+
}
|
|
233
|
+
if (this.target)
|
|
234
|
+
writeCoordinate(this.target.coordinates, this.coordinateCount, coordinate, this.dimension);
|
|
235
|
+
this.coordinateCount++;
|
|
236
|
+
}
|
|
237
|
+
/** Begins an event-driven geometry. Events are accepted by both measure and write builders. */
|
|
238
|
+
beginGeometry(type, dimension = this.dimension, _count) {
|
|
239
|
+
this.eventStack.push({ type, dimension, rings: [], polygons: [], children: [] });
|
|
240
|
+
return this;
|
|
241
|
+
}
|
|
242
|
+
/** Begins a polygon part inside an event-built MultiPolygon. */
|
|
243
|
+
beginPolygon() {
|
|
244
|
+
const state = this.eventStack[this.eventStack.length - 1];
|
|
245
|
+
if (!state || state.type !== "MultiPolygon") {
|
|
246
|
+
throw new Error("beginPolygon must follow beginGeometry('MultiPolygon')");
|
|
247
|
+
}
|
|
248
|
+
state.currentPolygon = [];
|
|
249
|
+
state.polygons.push(state.currentPolygon);
|
|
250
|
+
state.currentRing = void 0;
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
/** Begins a ring/part in the current event geometry. */
|
|
254
|
+
beginRing(_count) {
|
|
255
|
+
const state = this.eventStack[this.eventStack.length - 1];
|
|
256
|
+
if (!state)
|
|
257
|
+
throw new Error("beginRing must follow beginGeometry");
|
|
258
|
+
state.currentRing = [];
|
|
259
|
+
if (state.type === "MultiPolygon") {
|
|
260
|
+
if (!state.currentPolygon)
|
|
261
|
+
this.beginPolygon();
|
|
262
|
+
state.currentPolygon.push(state.currentRing);
|
|
263
|
+
} else {
|
|
264
|
+
state.rings.push(state.currentRing);
|
|
265
|
+
}
|
|
266
|
+
return this;
|
|
267
|
+
}
|
|
268
|
+
/** Writes one coordinate into the current event ring or point. */
|
|
269
|
+
writeCoordinate(x, y, z, m) {
|
|
270
|
+
const state = this.eventStack[this.eventStack.length - 1];
|
|
271
|
+
if (!state)
|
|
272
|
+
throw new Error("writeCoordinate must follow beginGeometry");
|
|
273
|
+
const coordinate = Array.isArray(x) ? [...x] : [x, y, ...z === void 0 ? [] : [z], ...m === void 0 ? [] : [m]];
|
|
274
|
+
const size = getGeoArrowDimensionSize(state.dimension);
|
|
275
|
+
if (coordinate.length !== size)
|
|
276
|
+
throw new Error(`Expected ${size} coordinate values for ${state.dimension}`);
|
|
277
|
+
if (state.type === "Point") {
|
|
278
|
+
state.rings = [[coordinate]];
|
|
279
|
+
return this;
|
|
280
|
+
}
|
|
281
|
+
if (!state.currentRing)
|
|
282
|
+
this.beginRing();
|
|
283
|
+
state.currentRing.push(coordinate);
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
/** Ends the current event geometry and appends it to the builder/parent. */
|
|
287
|
+
endGeometry() {
|
|
288
|
+
var _a;
|
|
289
|
+
const state = this.eventStack.pop();
|
|
290
|
+
if (!state)
|
|
291
|
+
throw new Error("endGeometry without beginGeometry");
|
|
292
|
+
const coordinates = state.rings;
|
|
293
|
+
let geometry;
|
|
294
|
+
switch (state.type) {
|
|
295
|
+
case "Point":
|
|
296
|
+
geometry = { type: "Point", coordinates: ((_a = coordinates[0]) == null ? void 0 : _a[0]) || [] };
|
|
297
|
+
break;
|
|
298
|
+
case "LineString":
|
|
299
|
+
geometry = { type: "LineString", coordinates: coordinates[0] || [] };
|
|
300
|
+
break;
|
|
301
|
+
case "MultiPoint":
|
|
302
|
+
geometry = { type: "MultiPoint", coordinates: coordinates.flat() };
|
|
303
|
+
break;
|
|
304
|
+
case "Polygon":
|
|
305
|
+
geometry = { type: "Polygon", coordinates };
|
|
306
|
+
break;
|
|
307
|
+
case "MultiLineString":
|
|
308
|
+
geometry = { type: "MultiLineString", coordinates };
|
|
309
|
+
break;
|
|
310
|
+
case "MultiPolygon":
|
|
311
|
+
geometry = {
|
|
312
|
+
type: "MultiPolygon",
|
|
313
|
+
coordinates: state.polygons.length ? state.polygons : [coordinates]
|
|
314
|
+
};
|
|
315
|
+
break;
|
|
316
|
+
case "GeometryCollection":
|
|
317
|
+
geometry = { type: "GeometryCollection", geometries: state.children };
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
const parent = this.eventStack[this.eventStack.length - 1];
|
|
321
|
+
if ((parent == null ? void 0 : parent.type) === "GeometryCollection")
|
|
322
|
+
parent.children.push(geometry);
|
|
323
|
+
else
|
|
324
|
+
this.append(geometry);
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
writeOffset(target, index, value) {
|
|
328
|
+
if (!target)
|
|
329
|
+
return;
|
|
330
|
+
if (target instanceof BigInt64Array)
|
|
331
|
+
target[index] = BigInt(value);
|
|
332
|
+
else
|
|
333
|
+
target[index] = value;
|
|
334
|
+
}
|
|
335
|
+
initializeTargetOffsets(target) {
|
|
336
|
+
this.writeOffset(target.geometryOffsets, 0, 0);
|
|
337
|
+
this.writeOffset(target.partOffsets, 0, 0);
|
|
338
|
+
this.writeOffset(target.ringOffsets, 0, 0);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
function allocateGeoArrowBuilderTarget(measurement, options) {
|
|
342
|
+
const dimension = options.dimension || "xy";
|
|
343
|
+
const size = getGeoArrowDimensionSize(dimension);
|
|
344
|
+
const FloatArray = options.coordinateType === "float32" ? Float32Array : Float64Array;
|
|
345
|
+
const coordinateLayout = options.coordinateLayout || "interleaved";
|
|
346
|
+
const coordinates = coordinateLayout === "interleaved" ? new FloatArray(measurement.coordinateCount * size) : makeSeparatedCoordinateTarget(FloatArray, measurement.coordinateCount, dimension);
|
|
347
|
+
const OffsetArray = options.offsetType === "int64" ? BigInt64Array : Int32Array;
|
|
348
|
+
return {
|
|
349
|
+
validity: new Uint8Array(Math.ceil(measurement.length / 8)),
|
|
350
|
+
coordinates,
|
|
351
|
+
geometryOffsets: measurement.geometryOffsetCount ? new OffsetArray(measurement.geometryOffsetCount) : void 0,
|
|
352
|
+
partOffsets: measurement.partOffsetCount ? new OffsetArray(measurement.partOffsetCount) : void 0,
|
|
353
|
+
ringOffsets: measurement.ringOffsetCount ? new OffsetArray(measurement.ringOffsetCount) : void 0
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function makeGeoArrowColumnFromGeometryRows(rows, options = {}) {
|
|
357
|
+
const geometryTypes = [...new Set(rows.filter(Boolean).map((row) => row.type))];
|
|
358
|
+
const dimension = options.dimension || inferRowsDimension(rows);
|
|
359
|
+
if (options.encoding === "geoarrow.geometry") {
|
|
360
|
+
return {
|
|
361
|
+
encoding: "geoarrow.geometry",
|
|
362
|
+
dimension,
|
|
363
|
+
coordinateLayout: options.coordinateLayout || "interleaved",
|
|
364
|
+
chunks: [makeDenseUnionArray(rows, options, dimension)]
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
if (geometryTypes.length === 0) {
|
|
368
|
+
return GeoArrowBuilder.build(rows, { ...options, dimension, encoding: "geoarrow.point" });
|
|
369
|
+
}
|
|
370
|
+
if (geometryTypes.length === 1 && geometryTypes[0] !== "GeometryCollection") {
|
|
371
|
+
return GeoArrowBuilder.build(rows, {
|
|
372
|
+
...options,
|
|
373
|
+
dimension,
|
|
374
|
+
encoding: getGeoArrowEncodingForGeometry(geometryTypes[0])
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
if (geometryTypes.length === 1 && geometryTypes[0] === "GeometryCollection") {
|
|
378
|
+
return {
|
|
379
|
+
encoding: "geoarrow.geometrycollection",
|
|
380
|
+
dimension,
|
|
381
|
+
coordinateLayout: options.coordinateLayout || "interleaved",
|
|
382
|
+
chunks: [makeGeometryCollectionArray(rows, options, dimension)]
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
encoding: "geoarrow.geometry",
|
|
387
|
+
dimension,
|
|
388
|
+
coordinateLayout: options.coordinateLayout || "interleaved",
|
|
389
|
+
chunks: [makeDenseUnionArray(rows, options, dimension)]
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function makeDenseUnionArray(rows, options, dimension) {
|
|
393
|
+
const nonNullTypes = [...new Set(rows.filter(Boolean).map((row) => row.type))];
|
|
394
|
+
const fallbackType = nonNullTypes[0] || "Point";
|
|
395
|
+
const childRows = /* @__PURE__ */ new Map();
|
|
396
|
+
for (const type of nonNullTypes.length ? nonNullTypes : [fallbackType])
|
|
397
|
+
childRows.set(type, []);
|
|
398
|
+
const typeIds = new Int8Array(rows.length);
|
|
399
|
+
const valueOffsets = new Int32Array(rows.length);
|
|
400
|
+
const validity = new Uint8Array(Math.ceil(rows.length / 8));
|
|
401
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
402
|
+
const geometry = rows[rowIndex];
|
|
403
|
+
const type = (geometry == null ? void 0 : geometry.type) || fallbackType;
|
|
404
|
+
const values = childRows.get(type) || [];
|
|
405
|
+
typeIds[rowIndex] = getGeometryTypeId(type, dimension);
|
|
406
|
+
valueOffsets[rowIndex] = values.length;
|
|
407
|
+
if (geometry) {
|
|
408
|
+
values.push(geometry);
|
|
409
|
+
childRows.set(type, values);
|
|
410
|
+
setValidityBit(validity, rowIndex);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
const children = [...childRows.entries()].sort(([left], [right]) => getGeometryTypeId(left, dimension) - getGeometryTypeId(right, dimension)).map(([type, values]) => {
|
|
414
|
+
const data = type === "GeometryCollection" ? makeGeometryCollectionArray(values, options, dimension) : GeoArrowBuilder.build(values, {
|
|
415
|
+
...options,
|
|
416
|
+
dimension,
|
|
417
|
+
encoding: getGeoArrowEncodingForGeometry(type)
|
|
418
|
+
}).chunks[0];
|
|
419
|
+
return {
|
|
420
|
+
name: type,
|
|
421
|
+
typeId: getGeometryTypeId(type, dimension),
|
|
422
|
+
encoding: getGeoArrowEncodingForGeometry(type),
|
|
423
|
+
dimension,
|
|
424
|
+
coordinateLayout: options.coordinateLayout || "interleaved",
|
|
425
|
+
data
|
|
426
|
+
};
|
|
427
|
+
});
|
|
428
|
+
return {
|
|
429
|
+
kind: "dense-union",
|
|
430
|
+
length: rows.length,
|
|
431
|
+
typeIds,
|
|
432
|
+
valueOffsets,
|
|
433
|
+
children,
|
|
434
|
+
validity: { values: validity }
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function makeGeometryCollectionArray(rows, options, dimension) {
|
|
438
|
+
const offsets = new Int32Array(rows.length + 1);
|
|
439
|
+
const validity = new Uint8Array(Math.ceil(rows.length / 8));
|
|
440
|
+
const flattened = [];
|
|
441
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
442
|
+
const row = rows[rowIndex];
|
|
443
|
+
if ((row == null ? void 0 : row.type) === "GeometryCollection") {
|
|
444
|
+
flattened.push(...row.geometries);
|
|
445
|
+
setValidityBit(validity, rowIndex);
|
|
446
|
+
}
|
|
447
|
+
offsets[rowIndex + 1] = flattened.length;
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
kind: "list",
|
|
451
|
+
length: rows.length,
|
|
452
|
+
offsets,
|
|
453
|
+
child: makeDenseUnionArray(flattened, options, dimension),
|
|
454
|
+
validity: { values: validity }
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
function makeCoordinateArray(coordinates, coordinateCount, dimension, layout) {
|
|
458
|
+
const size = getGeoArrowDimensionSize(dimension);
|
|
459
|
+
if (layout === "interleaved") {
|
|
460
|
+
const values = coordinates;
|
|
461
|
+
return {
|
|
462
|
+
kind: "fixed-size-list",
|
|
463
|
+
length: coordinateCount,
|
|
464
|
+
size,
|
|
465
|
+
child: { kind: "primitive", length: coordinateCount * size, values }
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
const separated = coordinates;
|
|
469
|
+
const children = {
|
|
470
|
+
x: { kind: "primitive", length: coordinateCount, values: separated.x },
|
|
471
|
+
y: { kind: "primitive", length: coordinateCount, values: separated.y }
|
|
472
|
+
};
|
|
473
|
+
if (separated.z) {
|
|
474
|
+
children["z"] = { kind: "primitive", length: coordinateCount, values: separated.z };
|
|
475
|
+
}
|
|
476
|
+
if (separated.m) {
|
|
477
|
+
children["m"] = { kind: "primitive", length: coordinateCount, values: separated.m };
|
|
478
|
+
}
|
|
479
|
+
return { kind: "struct", length: coordinateCount, children };
|
|
480
|
+
}
|
|
481
|
+
function makeSeparatedCoordinateTarget(FloatArray, count, dimension) {
|
|
482
|
+
return {
|
|
483
|
+
x: new FloatArray(count),
|
|
484
|
+
y: new FloatArray(count),
|
|
485
|
+
z: dimension === "xyz" || dimension === "xyzm" ? new FloatArray(count) : void 0,
|
|
486
|
+
m: dimension === "xym" || dimension === "xyzm" ? new FloatArray(count) : void 0
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function writeCoordinate(target, coordinateIndex, coordinate, dimension) {
|
|
490
|
+
if (target instanceof Float32Array || target instanceof Float64Array) {
|
|
491
|
+
target.set(coordinate, coordinateIndex * coordinate.length);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
target.x[coordinateIndex] = coordinate[0];
|
|
495
|
+
target.y[coordinateIndex] = coordinate[1];
|
|
496
|
+
if (dimension === "xyz")
|
|
497
|
+
target.z[coordinateIndex] = coordinate[2];
|
|
498
|
+
else if (dimension === "xym")
|
|
499
|
+
target.m[coordinateIndex] = coordinate[2];
|
|
500
|
+
else if (dimension === "xyzm") {
|
|
501
|
+
target.z[coordinateIndex] = coordinate[2];
|
|
502
|
+
target.m[coordinateIndex] = coordinate[3];
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function setValidityBit(validity, index) {
|
|
506
|
+
validity[index >> 3] |= 1 << (index & 7);
|
|
507
|
+
}
|
|
508
|
+
function getBuilderDepth(encoding) {
|
|
509
|
+
switch (encoding) {
|
|
510
|
+
case "geoarrow.point":
|
|
511
|
+
return 0;
|
|
512
|
+
case "geoarrow.linestring":
|
|
513
|
+
case "geoarrow.multipoint":
|
|
514
|
+
return 1;
|
|
515
|
+
case "geoarrow.polygon":
|
|
516
|
+
case "geoarrow.multilinestring":
|
|
517
|
+
return 2;
|
|
518
|
+
case "geoarrow.multipolygon":
|
|
519
|
+
return 3;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
function getGeometryTypeId(type, dimension = "xy") {
|
|
523
|
+
const family = [
|
|
524
|
+
"Point",
|
|
525
|
+
"LineString",
|
|
526
|
+
"Polygon",
|
|
527
|
+
"MultiPoint",
|
|
528
|
+
"MultiLineString",
|
|
529
|
+
"MultiPolygon",
|
|
530
|
+
"GeometryCollection"
|
|
531
|
+
].indexOf(type);
|
|
532
|
+
const dimensionIndex = ["xy", "xyz", "xym", "xyzm"].indexOf(dimension);
|
|
533
|
+
return family < 0 || dimensionIndex < 0 ? 1 : family * 4 + dimensionIndex + 1;
|
|
534
|
+
}
|
|
535
|
+
function inferRowsDimension(rows) {
|
|
536
|
+
let size = 2;
|
|
537
|
+
const visit = (value) => {
|
|
538
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
539
|
+
return;
|
|
540
|
+
if (typeof value[0] === "number")
|
|
541
|
+
size = Math.max(size, value.length);
|
|
542
|
+
else
|
|
543
|
+
for (const child of value)
|
|
544
|
+
visit(child);
|
|
545
|
+
};
|
|
546
|
+
const visitGeometry = (geometry) => {
|
|
547
|
+
if (geometry.type === "GeometryCollection") {
|
|
548
|
+
for (const child of geometry.geometries)
|
|
549
|
+
visitGeometry(child);
|
|
550
|
+
} else {
|
|
551
|
+
visit(geometry.coordinates);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
for (const row of rows) {
|
|
555
|
+
if (row)
|
|
556
|
+
visitGeometry(row);
|
|
557
|
+
}
|
|
558
|
+
return size >= 4 ? "xyzm" : size === 3 ? "xyz" : "xy";
|
|
559
|
+
}
|
|
560
|
+
function assertTargetCapacity(target, measurement, size) {
|
|
561
|
+
const coordinateLength = target.coordinates instanceof Float32Array || target.coordinates instanceof Float64Array ? target.coordinates.length / size : target.coordinates.x.length;
|
|
562
|
+
if (coordinateLength < measurement.coordinateCount || target.validity.length * 8 < measurement.length) {
|
|
563
|
+
throw new Error("GeoArrowBuilder target is smaller than its measured output");
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// dist/layout.js
|
|
568
|
+
function isGeoArrowValueValid(validity, index) {
|
|
569
|
+
if (!validity)
|
|
570
|
+
return true;
|
|
571
|
+
const bitIndex = (validity.bitOffset || 0) + index;
|
|
572
|
+
return Boolean(validity.values[bitIndex >> 3] & 1 << (bitIndex & 7));
|
|
573
|
+
}
|
|
574
|
+
function materializeGeometryRow(array, rowIndex, encoding) {
|
|
575
|
+
if (!isGeoArrowValueValid(array.validity, rowIndex))
|
|
576
|
+
return null;
|
|
577
|
+
if (encoding === "geoarrow.geometry") {
|
|
578
|
+
if (array.kind !== "dense-union")
|
|
579
|
+
return null;
|
|
580
|
+
return materializeUnionRow(array, rowIndex);
|
|
581
|
+
}
|
|
582
|
+
if (encoding === "geoarrow.geometrycollection") {
|
|
583
|
+
if (array.kind !== "list")
|
|
584
|
+
return null;
|
|
585
|
+
const [first, last] = getListRange(array, rowIndex);
|
|
586
|
+
const geometries = [];
|
|
587
|
+
for (let index = first; index < last; index++) {
|
|
588
|
+
if (array.child.kind !== "dense-union")
|
|
589
|
+
continue;
|
|
590
|
+
const geometry = materializeUnionRow(array.child, index);
|
|
591
|
+
if (geometry)
|
|
592
|
+
geometries.push(geometry);
|
|
593
|
+
}
|
|
594
|
+
return { type: "GeometryCollection", geometries };
|
|
595
|
+
}
|
|
596
|
+
const geometryType = getGeoArrowGeometryType(encoding);
|
|
597
|
+
if (!geometryType || geometryType === "GeometryCollection")
|
|
598
|
+
return null;
|
|
599
|
+
const depth = getEncodingDepth(encoding);
|
|
600
|
+
const coordinates = readNestedCoordinates(array, rowIndex, depth);
|
|
601
|
+
if (!coordinates)
|
|
602
|
+
return null;
|
|
603
|
+
return { type: geometryType, coordinates };
|
|
604
|
+
}
|
|
605
|
+
function getGeoArrowOffset(offsets, index) {
|
|
606
|
+
const value = offsets[index];
|
|
607
|
+
const numericValue = typeof value === "bigint" ? Number(value) : value;
|
|
608
|
+
if (!Number.isSafeInteger(numericValue)) {
|
|
609
|
+
throw new Error(`GeoArrow offset ${String(value)} exceeds JavaScript's safe integer range`);
|
|
610
|
+
}
|
|
611
|
+
return numericValue;
|
|
612
|
+
}
|
|
613
|
+
function getListRange(list, rowIndex) {
|
|
614
|
+
const offsetIndex = (list.offset || 0) + rowIndex;
|
|
615
|
+
const baseValue = list.offsetBase ?? 0;
|
|
616
|
+
const base = typeof baseValue === "bigint" ? Number(baseValue) : baseValue;
|
|
617
|
+
return [
|
|
618
|
+
getGeoArrowOffset(list.offsets, offsetIndex) - base,
|
|
619
|
+
getGeoArrowOffset(list.offsets, offsetIndex + 1) - base
|
|
620
|
+
];
|
|
621
|
+
}
|
|
622
|
+
function readNestedCoordinates(array, index, depth) {
|
|
623
|
+
if (depth === 0)
|
|
624
|
+
return readCoordinate(array, index);
|
|
625
|
+
if (array.kind !== "list" || !isGeoArrowValueValid(array.validity, index))
|
|
626
|
+
return null;
|
|
627
|
+
const [first, last] = getListRange(array, index);
|
|
628
|
+
const values = [];
|
|
629
|
+
for (let childIndex = first; childIndex < last; childIndex++) {
|
|
630
|
+
const value = readNestedCoordinates(array.child, childIndex, depth - 1);
|
|
631
|
+
if (value !== null)
|
|
632
|
+
values.push(value);
|
|
633
|
+
}
|
|
634
|
+
return values;
|
|
635
|
+
}
|
|
636
|
+
function readCoordinate(array, index) {
|
|
637
|
+
if (!isGeoArrowValueValid(array.validity, index))
|
|
638
|
+
return null;
|
|
639
|
+
if (array.kind === "fixed-size-list") {
|
|
640
|
+
const listIndex = (array.offset || 0) + index;
|
|
641
|
+
const coordinate = [];
|
|
642
|
+
for (let component = 0; component < array.size; component++) {
|
|
643
|
+
coordinate.push(readPrimitive(array.child, listIndex * array.size + component));
|
|
644
|
+
}
|
|
645
|
+
return coordinate;
|
|
646
|
+
}
|
|
647
|
+
if (array.kind === "struct") {
|
|
648
|
+
const structIndex = (array.offset || 0) + index;
|
|
649
|
+
const coordinate = [];
|
|
650
|
+
for (const name of ["x", "y", "z", "m"]) {
|
|
651
|
+
const child = array.children[name];
|
|
652
|
+
if (child)
|
|
653
|
+
coordinate.push(readPrimitive(child, structIndex));
|
|
654
|
+
}
|
|
655
|
+
return coordinate.length >= 2 ? coordinate : null;
|
|
656
|
+
}
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
function readPrimitive(array, index) {
|
|
660
|
+
if (array.kind !== "primitive")
|
|
661
|
+
throw new Error("GeoArrow coordinate child must be primitive");
|
|
662
|
+
const valueIndex = (array.offset || 0) + index * (array.stride || 1);
|
|
663
|
+
return Number(array.values[valueIndex]);
|
|
664
|
+
}
|
|
665
|
+
function materializeUnionRow(union, rowIndex) {
|
|
666
|
+
if (!isGeoArrowValueValid(union.validity, rowIndex))
|
|
667
|
+
return null;
|
|
668
|
+
const physicalIndex = (union.offset || 0) + rowIndex;
|
|
669
|
+
const typeId = union.typeIds[physicalIndex];
|
|
670
|
+
const valueOffset = union.valueOffsets[physicalIndex];
|
|
671
|
+
const child = union.children.find((candidate) => candidate.typeId === typeId);
|
|
672
|
+
if (!child || valueOffset < 0 || valueOffset >= child.data.length)
|
|
673
|
+
return null;
|
|
674
|
+
return materializeGeometryRow(child.data, valueOffset, child.encoding || getEncodingFromChildName(child.name));
|
|
675
|
+
}
|
|
676
|
+
function getEncodingFromChildName(name) {
|
|
677
|
+
const normalized = name.replace(/[^a-z]/gi, "").toLowerCase();
|
|
678
|
+
switch (normalized) {
|
|
679
|
+
case "point":
|
|
680
|
+
return "geoarrow.point";
|
|
681
|
+
case "linestring":
|
|
682
|
+
return "geoarrow.linestring";
|
|
683
|
+
case "polygon":
|
|
684
|
+
return "geoarrow.polygon";
|
|
685
|
+
case "multipoint":
|
|
686
|
+
return "geoarrow.multipoint";
|
|
687
|
+
case "multilinestring":
|
|
688
|
+
return "geoarrow.multilinestring";
|
|
689
|
+
case "multipolygon":
|
|
690
|
+
return "geoarrow.multipolygon";
|
|
691
|
+
case "geometrycollection":
|
|
692
|
+
return "geoarrow.geometrycollection";
|
|
693
|
+
default:
|
|
694
|
+
throw new Error(`Unknown GeoArrow dense-union child ${name}`);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
function getEncodingDepth(encoding) {
|
|
698
|
+
switch (encoding) {
|
|
699
|
+
case "geoarrow.point":
|
|
700
|
+
return 0;
|
|
701
|
+
case "geoarrow.linestring":
|
|
702
|
+
case "geoarrow.multipoint":
|
|
703
|
+
return 1;
|
|
704
|
+
case "geoarrow.polygon":
|
|
705
|
+
case "geoarrow.multilinestring":
|
|
706
|
+
return 2;
|
|
707
|
+
case "geoarrow.multipolygon":
|
|
708
|
+
return 3;
|
|
709
|
+
default:
|
|
710
|
+
return 0;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// dist/codecs.js
|
|
715
|
+
var textEncoder = new TextEncoder();
|
|
716
|
+
var textDecoder = new TextDecoder();
|
|
717
|
+
function decodeGeoArrowWKB(column) {
|
|
718
|
+
if (column.encoding !== "geoarrow.wkb")
|
|
719
|
+
throw new Error("Expected a geoarrow.wkb column");
|
|
720
|
+
const rows = normalizeRowsToDimension(decodeSerializedRows(column, (bytes) => (0, import_wkb.parseWKB)(bytes).geometry), column.dimension);
|
|
721
|
+
return copyMetadata(column, makeGeoArrowColumnFromGeometryRows(rows, { dimension: column.dimension }));
|
|
722
|
+
}
|
|
723
|
+
function encodeGeoArrowWKB(column) {
|
|
724
|
+
if (column.encoding === "geoarrow.wkb")
|
|
725
|
+
return column;
|
|
726
|
+
const writers = [];
|
|
727
|
+
const dimensions = [];
|
|
728
|
+
for (const chunk of column.chunks) {
|
|
729
|
+
for (let rowIndex = 0; rowIndex < chunk.length; rowIndex++) {
|
|
730
|
+
if (!isGeoArrowValueValid(chunk.validity, rowIndex)) {
|
|
731
|
+
writers.push(null);
|
|
732
|
+
dimensions.push(column.dimension);
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
dimensions.push(getPhysicalGeometryDimension(chunk, rowIndex, column.encoding, column.dimension));
|
|
736
|
+
writers.push((builder) => writePhysicalGeometry(builder, chunk, rowIndex, column.encoding, column.dimension));
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
const built = import_wkb2.WKBBuilder.buildGeometryArray(writers, {
|
|
740
|
+
dimension: column.dimension,
|
|
741
|
+
dimensionResolver: (index) => dimensions[index] || column.dimension
|
|
742
|
+
});
|
|
743
|
+
return copyMetadata(column, {
|
|
744
|
+
encoding: "geoarrow.wkb",
|
|
745
|
+
dimension: column.dimension,
|
|
746
|
+
coordinateLayout: null,
|
|
747
|
+
chunks: [
|
|
748
|
+
{
|
|
749
|
+
kind: "serialized",
|
|
750
|
+
encoding: "binary",
|
|
751
|
+
length: writers.length,
|
|
752
|
+
offsets: built.valueOffsets,
|
|
753
|
+
values: built.values,
|
|
754
|
+
...built.nullBitmap ? { validity: { values: built.nullBitmap } } : {}
|
|
755
|
+
}
|
|
756
|
+
]
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
function decodeGeoArrowWKT(column) {
|
|
760
|
+
if (column.encoding !== "geoarrow.wkt")
|
|
761
|
+
throw new Error("Expected a geoarrow.wkt column");
|
|
762
|
+
const rows = normalizeRowsToDimension(decodeSerializedRows(column, (bytes) => (0, import_wkb.parseWKT)(textDecoder.decode(bytes))), column.dimension);
|
|
763
|
+
return copyMetadata(column, makeGeoArrowColumnFromGeometryRows(rows, { dimension: column.dimension }));
|
|
764
|
+
}
|
|
765
|
+
function encodeGeoArrowWKT(column) {
|
|
766
|
+
if (column.encoding === "geoarrow.wkt")
|
|
767
|
+
return column;
|
|
768
|
+
const values = [];
|
|
769
|
+
for (const chunk of column.chunks) {
|
|
770
|
+
for (let rowIndex = 0; rowIndex < chunk.length; rowIndex++) {
|
|
771
|
+
const row = isGeoArrowValueValid(chunk.validity, rowIndex) ? materializeGeometryRow(chunk, rowIndex, column.encoding) : null;
|
|
772
|
+
values.push(row ? textEncoder.encode((0, import_wkb.formatWKT)(row, column.dimension)) : null);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
return copyMetadata(column, makeSerializedColumn(values, "geoarrow.wkt", column.dimension));
|
|
776
|
+
}
|
|
777
|
+
function writePhysicalGeometry(builder, array, rowIndex, encoding, dimension) {
|
|
778
|
+
const depth = getEncodingDepth2(encoding);
|
|
779
|
+
if (encoding === "geoarrow.geometry" && array.kind === "dense-union") {
|
|
780
|
+
const physical = (array.offset || 0) + rowIndex;
|
|
781
|
+
const typeId = array.typeIds[physical];
|
|
782
|
+
const child = array.children.find((candidate) => candidate.typeId === typeId);
|
|
783
|
+
if (!child)
|
|
784
|
+
throw new Error("Dense-union row references an unknown child");
|
|
785
|
+
const childDimension = child.dimension || dimension;
|
|
786
|
+
builder.withDimension(childDimension, () => writePhysicalGeometry(builder, child.data, array.valueOffsets[physical], child.encoding || encodingFromName(child.name), childDimension));
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
if (encoding === "geoarrow.geometrycollection" && array.kind === "list") {
|
|
790
|
+
const [first, last] = getListRange2(array, rowIndex);
|
|
791
|
+
builder.beginGeometry("GeometryCollection", last - first);
|
|
792
|
+
if (array.child.kind !== "dense-union")
|
|
793
|
+
throw new Error("GeometryCollection requires dense union child");
|
|
794
|
+
const union = array.child;
|
|
795
|
+
for (let index = first; index < last; index++) {
|
|
796
|
+
const physical = (union.offset || 0) + index;
|
|
797
|
+
const child = union.children.find((candidate) => candidate.typeId === union.typeIds[physical]);
|
|
798
|
+
if (child) {
|
|
799
|
+
const childDimension = child.dimension || dimension;
|
|
800
|
+
builder.withDimension(childDimension, () => writePhysicalGeometry(builder, child.data, union.valueOffsets[physical], child.encoding || encodingFromName(child.name), childDimension));
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
if (array.kind !== "list" && depth > 0)
|
|
806
|
+
throw new Error(`Invalid ${encoding} storage`);
|
|
807
|
+
const writeCoordinate2 = (leaf, index) => {
|
|
808
|
+
const coordinate = readPhysicalCoordinate(leaf, index);
|
|
809
|
+
if (!coordinate)
|
|
810
|
+
throw new Error("Invalid GeoArrow coordinate storage");
|
|
811
|
+
if (dimension === "xym")
|
|
812
|
+
builder.writeCoordinate(coordinate[0], coordinate[1], void 0, coordinate[2]);
|
|
813
|
+
else if (dimension === "xyzm")
|
|
814
|
+
builder.writeCoordinate(coordinate[0], coordinate[1], coordinate[2], coordinate[3]);
|
|
815
|
+
else
|
|
816
|
+
builder.writeCoordinate(coordinate[0], coordinate[1], coordinate[2]);
|
|
817
|
+
};
|
|
818
|
+
const writeSequence = (leaf, first, last) => {
|
|
819
|
+
for (let index = first; index < last; index++)
|
|
820
|
+
writeCoordinate2(leaf, index);
|
|
821
|
+
};
|
|
822
|
+
if (encoding === "geoarrow.point") {
|
|
823
|
+
builder.beginPoint();
|
|
824
|
+
writeCoordinate2(array, rowIndex);
|
|
825
|
+
} else if (encoding === "geoarrow.linestring" || encoding === "geoarrow.multipoint") {
|
|
826
|
+
const [first, last] = getListRange2(array, rowIndex);
|
|
827
|
+
if (encoding === "geoarrow.linestring") {
|
|
828
|
+
builder.beginLineString(last - first);
|
|
829
|
+
writeSequence(array.child, first, last);
|
|
830
|
+
} else {
|
|
831
|
+
builder.beginMultiPoint(last - first);
|
|
832
|
+
const leaf = array.child;
|
|
833
|
+
for (let index = first; index < last; index++) {
|
|
834
|
+
builder.beginPoint();
|
|
835
|
+
writeCoordinate2(leaf, index);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
} else if (encoding === "geoarrow.polygon" || encoding === "geoarrow.multilinestring") {
|
|
839
|
+
const [first, last] = getListRange2(array, rowIndex);
|
|
840
|
+
const parts = array.child;
|
|
841
|
+
if (encoding === "geoarrow.polygon")
|
|
842
|
+
builder.beginPolygon(last - first);
|
|
843
|
+
else
|
|
844
|
+
builder.beginMultiLineString(last - first);
|
|
845
|
+
for (let partIndex = first; partIndex < last; partIndex++) {
|
|
846
|
+
const [ringFirst, ringLast] = getListRange2(parts, partIndex);
|
|
847
|
+
const leaf = parts.child;
|
|
848
|
+
if (encoding === "geoarrow.polygon")
|
|
849
|
+
builder.beginLinearRing(ringLast - ringFirst);
|
|
850
|
+
else
|
|
851
|
+
builder.beginLineString(ringLast - ringFirst);
|
|
852
|
+
writeSequence(leaf, ringFirst, ringLast);
|
|
853
|
+
}
|
|
854
|
+
} else if (encoding === "geoarrow.multipolygon") {
|
|
855
|
+
const [first, last] = getListRange2(array, rowIndex);
|
|
856
|
+
const polygons = array.child;
|
|
857
|
+
builder.beginMultiPolygon(last - first);
|
|
858
|
+
for (let polygonIndex = first; polygonIndex < last; polygonIndex++) {
|
|
859
|
+
const [partFirst, partLast] = getListRange2(polygons, polygonIndex);
|
|
860
|
+
const parts = polygons.child;
|
|
861
|
+
builder.beginPolygon(partLast - partFirst);
|
|
862
|
+
for (let partIndex = partFirst; partIndex < partLast; partIndex++) {
|
|
863
|
+
const [ringFirst, ringLast] = getListRange2(parts, partIndex);
|
|
864
|
+
builder.beginLinearRing(ringLast - ringFirst);
|
|
865
|
+
writeSequence(parts.child, ringFirst, ringLast);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
function getPhysicalGeometryDimension(array, rowIndex, encoding, dimension) {
|
|
871
|
+
if (encoding !== "geoarrow.geometry" || array.kind !== "dense-union")
|
|
872
|
+
return dimension;
|
|
873
|
+
const physical = (array.offset || 0) + rowIndex;
|
|
874
|
+
const child = array.children.find((candidate) => candidate.typeId === array.typeIds[physical]);
|
|
875
|
+
return (child == null ? void 0 : child.dimension) || dimension;
|
|
876
|
+
}
|
|
877
|
+
function readPhysicalCoordinate(array, index) {
|
|
878
|
+
if (array.kind === "fixed-size-list" && array.child.kind === "primitive") {
|
|
879
|
+
const logical = (array.offset || 0) + index;
|
|
880
|
+
const values = [];
|
|
881
|
+
for (let component = 0; component < array.size; component++)
|
|
882
|
+
values.push(Number(array.child.values[(array.child.offset || 0) + (logical * array.size + component) * (array.child.stride || 1)]));
|
|
883
|
+
return values;
|
|
884
|
+
}
|
|
885
|
+
if (array.kind === "struct") {
|
|
886
|
+
const logical = (array.offset || 0) + index;
|
|
887
|
+
return ["x", "y", "z", "m"].flatMap((name) => {
|
|
888
|
+
const child = array.children[name];
|
|
889
|
+
return (child == null ? void 0 : child.kind) === "primitive" ? [Number(child.values[(child.offset || 0) + logical * (child.stride || 1)])] : [];
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
return null;
|
|
893
|
+
}
|
|
894
|
+
function getListRange2(list, index) {
|
|
895
|
+
const offset = (list.offset || 0) + index;
|
|
896
|
+
const base = typeof (list.offsetBase ?? 0) === "bigint" ? Number(list.offsetBase) : Number(list.offsetBase ?? 0);
|
|
897
|
+
return [
|
|
898
|
+
getGeoArrowOffset(list.offsets, offset) - base,
|
|
899
|
+
getGeoArrowOffset(list.offsets, offset + 1) - base
|
|
900
|
+
];
|
|
901
|
+
}
|
|
902
|
+
function getEncodingDepth2(encoding) {
|
|
903
|
+
return encoding === "geoarrow.point" ? 0 : encoding === "geoarrow.linestring" || encoding === "geoarrow.multipoint" ? 1 : encoding === "geoarrow.polygon" || encoding === "geoarrow.multilinestring" ? 2 : 3;
|
|
904
|
+
}
|
|
905
|
+
function encodingFromName(name) {
|
|
906
|
+
return `geoarrow.${name.toLowerCase()}`;
|
|
907
|
+
}
|
|
908
|
+
function normalizeRowsToDimension(rows, dimension) {
|
|
909
|
+
const size = getGeoArrowDimensionSize(dimension);
|
|
910
|
+
const normalizeGeometry = (geometry) => {
|
|
911
|
+
if (geometry.type === "GeometryCollection") {
|
|
912
|
+
return { ...geometry, geometries: geometry.geometries.map(normalizeGeometry) };
|
|
913
|
+
}
|
|
914
|
+
return {
|
|
915
|
+
...geometry,
|
|
916
|
+
coordinates: normalizeCoordinateNesting(geometry.coordinates, size)
|
|
917
|
+
};
|
|
918
|
+
};
|
|
919
|
+
return rows.map((row) => row ? normalizeGeometry(row) : null);
|
|
920
|
+
}
|
|
921
|
+
function normalizeCoordinateNesting(value, size) {
|
|
922
|
+
if (value.length === 0)
|
|
923
|
+
return [];
|
|
924
|
+
if (typeof value[0] === "number") {
|
|
925
|
+
const coordinate = value.slice(0, size);
|
|
926
|
+
while (coordinate.length < size)
|
|
927
|
+
coordinate.push(0);
|
|
928
|
+
return coordinate;
|
|
929
|
+
}
|
|
930
|
+
return value.map((child) => normalizeCoordinateNesting(child, size));
|
|
931
|
+
}
|
|
932
|
+
function decodeSerializedRows(column, decoder) {
|
|
933
|
+
const rows = [];
|
|
934
|
+
for (const chunk of column.chunks) {
|
|
935
|
+
if (chunk.kind !== "serialized")
|
|
936
|
+
throw new Error("Serialized column contains native storage");
|
|
937
|
+
for (let rowIndex = 0; rowIndex < chunk.length; rowIndex++) {
|
|
938
|
+
if (!isGeoArrowValueValid(chunk.validity, rowIndex)) {
|
|
939
|
+
rows.push(null);
|
|
940
|
+
continue;
|
|
941
|
+
}
|
|
942
|
+
rows.push(decoder(getSerializedBytes(chunk, rowIndex)));
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
return rows;
|
|
946
|
+
}
|
|
947
|
+
function getSerializedBytes(array, rowIndex) {
|
|
948
|
+
var _a;
|
|
949
|
+
if (array.views) {
|
|
950
|
+
const viewIndex = ((array.offset || 0) + rowIndex) * 4;
|
|
951
|
+
const length = array.views[viewIndex];
|
|
952
|
+
if (length <= 12) {
|
|
953
|
+
const byteOffset2 = array.views.byteOffset + viewIndex * 4 + 4;
|
|
954
|
+
return new Uint8Array(array.views.buffer, byteOffset2, length);
|
|
955
|
+
}
|
|
956
|
+
const bufferIndex = array.views[viewIndex + 2];
|
|
957
|
+
const byteOffset = array.views[viewIndex + 3];
|
|
958
|
+
const data = (_a = array.dataBuffers) == null ? void 0 : _a[bufferIndex];
|
|
959
|
+
if (!data)
|
|
960
|
+
throw new Error(`Serialized view references missing data buffer ${bufferIndex}`);
|
|
961
|
+
return data.subarray(byteOffset, byteOffset + length);
|
|
962
|
+
}
|
|
963
|
+
const offsetIndex = (array.offset || 0) + rowIndex;
|
|
964
|
+
const baseValue = array.offsetBase ?? 0;
|
|
965
|
+
const base = typeof baseValue === "bigint" ? Number(baseValue) : baseValue;
|
|
966
|
+
const first = getGeoArrowOffset(array.offsets, offsetIndex) - base;
|
|
967
|
+
const last = getGeoArrowOffset(array.offsets, offsetIndex + 1) - base;
|
|
968
|
+
return array.values.subarray(first, last);
|
|
969
|
+
}
|
|
970
|
+
function makeSerializedColumn(rows, encoding, dimension) {
|
|
971
|
+
let byteLength = 0;
|
|
972
|
+
for (const row of rows)
|
|
973
|
+
byteLength += (row == null ? void 0 : row.byteLength) || 0;
|
|
974
|
+
const values = new Uint8Array(byteLength);
|
|
975
|
+
const offsets = new Int32Array(rows.length + 1);
|
|
976
|
+
const validity = new Uint8Array(Math.ceil(rows.length / 8));
|
|
977
|
+
let byteOffset = 0;
|
|
978
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
979
|
+
const row = rows[rowIndex];
|
|
980
|
+
if (row) {
|
|
981
|
+
values.set(row, byteOffset);
|
|
982
|
+
byteOffset += row.byteLength;
|
|
983
|
+
validity[rowIndex >> 3] |= 1 << (rowIndex & 7);
|
|
984
|
+
}
|
|
985
|
+
offsets[rowIndex + 1] = byteOffset;
|
|
986
|
+
}
|
|
987
|
+
const chunk = {
|
|
988
|
+
kind: "serialized",
|
|
989
|
+
encoding: encoding === "geoarrow.wkb" ? "binary" : "utf8",
|
|
990
|
+
length: rows.length,
|
|
991
|
+
offsets,
|
|
992
|
+
values,
|
|
993
|
+
validity: { values: validity }
|
|
994
|
+
};
|
|
995
|
+
return { encoding, dimension, coordinateLayout: null, chunks: [chunk] };
|
|
996
|
+
}
|
|
997
|
+
function copyMetadata(source, target) {
|
|
998
|
+
return {
|
|
999
|
+
...target,
|
|
1000
|
+
spatialReference: source.spatialReference,
|
|
1001
|
+
edges: source.edges,
|
|
1002
|
+
metadata: source.metadata
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
//# sourceMappingURL=wkb-entry.cjs.map
|