@loaders.gl/gis 4.0.0-beta.1 → 4.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +708 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/{esm/lib → lib}/binary-to-geojson.js +2 -2
- package/dist/lib/binary-to-geojson.js.map +1 -0
- package/dist/{esm/lib → lib}/extract-geometry-info.js +1 -1
- package/dist/lib/extract-geometry-info.js.map +1 -0
- package/dist/lib/flat-geojson-to-binary-types.js.map +1 -0
- package/dist/lib/flat-geojson-to-binary.js.map +1 -0
- package/dist/{esm/lib → lib}/geojson-to-binary.js +3 -3
- package/dist/lib/geojson-to-binary.js.map +1 -0
- package/dist/{esm/lib → lib}/geojson-to-flat-geojson.js +1 -1
- package/dist/lib/geojson-to-flat-geojson.js.map +1 -0
- package/dist/lib/transform.js.map +1 -0
- package/package.json +16 -8
- package/src/lib/flat-geojson-to-binary.ts +0 -1
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.d.ts.map +0 -1
- package/dist/es5/bundle.js +0 -6
- package/dist/es5/bundle.js.map +0 -1
- package/dist/es5/index.js +0 -53
- package/dist/es5/index.js.map +0 -1
- package/dist/es5/lib/binary-to-geojson.js +0 -221
- package/dist/es5/lib/binary-to-geojson.js.map +0 -1
- package/dist/es5/lib/extract-geometry-info.js +0 -167
- package/dist/es5/lib/extract-geometry-info.js.map +0 -1
- package/dist/es5/lib/flat-geojson-to-binary-types.js +0 -2
- package/dist/es5/lib/flat-geojson-to-binary-types.js.map +0 -1
- package/dist/es5/lib/flat-geojson-to-binary.js +0 -355
- package/dist/es5/lib/flat-geojson-to-binary.js.map +0 -1
- package/dist/es5/lib/geojson-to-binary.js +0 -28
- package/dist/es5/lib/geojson-to-binary.js.map +0 -1
- package/dist/es5/lib/geojson-to-flat-geojson.js +0 -136
- package/dist/es5/lib/geojson-to-flat-geojson.js.map +0 -1
- package/dist/es5/lib/transform.js +0 -57
- package/dist/es5/lib/transform.js.map +0 -1
- package/dist/esm/bundle.js +0 -4
- package/dist/esm/bundle.js.map +0 -1
- package/dist/esm/index.js +0 -6
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/lib/binary-to-geojson.js.map +0 -1
- package/dist/esm/lib/extract-geometry-info.js.map +0 -1
- package/dist/esm/lib/flat-geojson-to-binary-types.js.map +0 -1
- package/dist/esm/lib/flat-geojson-to-binary.js.map +0 -1
- package/dist/esm/lib/geojson-to-binary.js.map +0 -1
- package/dist/esm/lib/geojson-to-flat-geojson.js.map +0 -1
- package/dist/esm/lib/transform.js.map +0 -1
- package/src/bundle.ts +0 -4
- /package/dist/{esm/lib → lib}/flat-geojson-to-binary-types.js +0 -0
- /package/dist/{esm/lib → lib}/flat-geojson-to-binary.js +0 -0
- /package/dist/{esm/lib → lib}/transform.js +0 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
binaryToGeojson: () => binaryToGeojson,
|
|
24
|
+
binaryToGeometry: () => binaryToGeometry,
|
|
25
|
+
flatGeojsonToBinary: () => flatGeojsonToBinary,
|
|
26
|
+
geojsonToBinary: () => geojsonToBinary,
|
|
27
|
+
geojsonToFlatGeojson: () => geojsonToFlatGeojson,
|
|
28
|
+
transformBinaryCoords: () => transformBinaryCoords,
|
|
29
|
+
transformGeoJsonCoords: () => transformGeoJsonCoords
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(src_exports);
|
|
32
|
+
|
|
33
|
+
// src/lib/flat-geojson-to-binary.ts
|
|
34
|
+
var import_polygon = require("@math.gl/polygon");
|
|
35
|
+
function flatGeojsonToBinary(features, geometryInfo, options) {
|
|
36
|
+
const propArrayTypes = extractNumericPropTypes(features);
|
|
37
|
+
const numericPropKeys = Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array);
|
|
38
|
+
return fillArrays(
|
|
39
|
+
features,
|
|
40
|
+
{
|
|
41
|
+
propArrayTypes,
|
|
42
|
+
...geometryInfo
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
numericPropKeys: options && options.numericPropKeys || numericPropKeys,
|
|
46
|
+
PositionDataType: options ? options.PositionDataType : Float32Array,
|
|
47
|
+
triangulate: options ? options.triangulate : true
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
function extractNumericPropTypes(features) {
|
|
52
|
+
const propArrayTypes = {};
|
|
53
|
+
for (const feature of features) {
|
|
54
|
+
if (feature.properties) {
|
|
55
|
+
for (const key in feature.properties) {
|
|
56
|
+
const val = feature.properties[key];
|
|
57
|
+
propArrayTypes[key] = deduceArrayType(val, propArrayTypes[key]);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return propArrayTypes;
|
|
62
|
+
}
|
|
63
|
+
function fillArrays(features, geometryInfo, options) {
|
|
64
|
+
const {
|
|
65
|
+
pointPositionsCount,
|
|
66
|
+
pointFeaturesCount,
|
|
67
|
+
linePositionsCount,
|
|
68
|
+
linePathsCount,
|
|
69
|
+
lineFeaturesCount,
|
|
70
|
+
polygonPositionsCount,
|
|
71
|
+
polygonObjectsCount,
|
|
72
|
+
polygonRingsCount,
|
|
73
|
+
polygonFeaturesCount,
|
|
74
|
+
propArrayTypes,
|
|
75
|
+
coordLength
|
|
76
|
+
} = geometryInfo;
|
|
77
|
+
const { numericPropKeys = [], PositionDataType = Float32Array, triangulate = true } = options;
|
|
78
|
+
const hasGlobalId = features[0] && "id" in features[0];
|
|
79
|
+
const GlobalFeatureIdsDataType = features.length > 65535 ? Uint32Array : Uint16Array;
|
|
80
|
+
const points = {
|
|
81
|
+
type: "Point",
|
|
82
|
+
positions: new PositionDataType(pointPositionsCount * coordLength),
|
|
83
|
+
globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
|
|
84
|
+
featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
|
|
85
|
+
numericProps: {},
|
|
86
|
+
properties: [],
|
|
87
|
+
fields: []
|
|
88
|
+
};
|
|
89
|
+
const lines = {
|
|
90
|
+
type: "LineString",
|
|
91
|
+
pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
|
|
92
|
+
positions: new PositionDataType(linePositionsCount * coordLength),
|
|
93
|
+
globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
|
|
94
|
+
featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
|
|
95
|
+
numericProps: {},
|
|
96
|
+
properties: [],
|
|
97
|
+
fields: []
|
|
98
|
+
};
|
|
99
|
+
const polygons = {
|
|
100
|
+
type: "Polygon",
|
|
101
|
+
polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
|
|
102
|
+
primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
|
|
103
|
+
positions: new PositionDataType(polygonPositionsCount * coordLength),
|
|
104
|
+
globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
|
|
105
|
+
featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
|
|
106
|
+
numericProps: {},
|
|
107
|
+
properties: [],
|
|
108
|
+
fields: []
|
|
109
|
+
};
|
|
110
|
+
if (triangulate) {
|
|
111
|
+
polygons.triangles = [];
|
|
112
|
+
}
|
|
113
|
+
for (const object of [points, lines, polygons]) {
|
|
114
|
+
for (const propName of numericPropKeys) {
|
|
115
|
+
const T = propArrayTypes[propName];
|
|
116
|
+
object.numericProps[propName] = new T(object.positions.length / coordLength);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
lines.pathIndices[linePathsCount] = linePositionsCount;
|
|
120
|
+
polygons.polygonIndices[polygonObjectsCount] = polygonPositionsCount;
|
|
121
|
+
polygons.primitivePolygonIndices[polygonRingsCount] = polygonPositionsCount;
|
|
122
|
+
const indexMap = {
|
|
123
|
+
pointPosition: 0,
|
|
124
|
+
pointFeature: 0,
|
|
125
|
+
linePosition: 0,
|
|
126
|
+
linePath: 0,
|
|
127
|
+
lineFeature: 0,
|
|
128
|
+
polygonPosition: 0,
|
|
129
|
+
polygonObject: 0,
|
|
130
|
+
polygonRing: 0,
|
|
131
|
+
polygonFeature: 0,
|
|
132
|
+
feature: 0
|
|
133
|
+
};
|
|
134
|
+
for (const feature of features) {
|
|
135
|
+
const geometry = feature.geometry;
|
|
136
|
+
const properties = feature.properties || {};
|
|
137
|
+
switch (geometry.type) {
|
|
138
|
+
case "Point":
|
|
139
|
+
handlePoint(geometry, points, indexMap, coordLength, properties);
|
|
140
|
+
points.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
141
|
+
if (hasGlobalId) {
|
|
142
|
+
points.fields.push({ id: feature.id });
|
|
143
|
+
}
|
|
144
|
+
indexMap.pointFeature++;
|
|
145
|
+
break;
|
|
146
|
+
case "LineString":
|
|
147
|
+
handleLineString(geometry, lines, indexMap, coordLength, properties);
|
|
148
|
+
lines.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
149
|
+
if (hasGlobalId) {
|
|
150
|
+
lines.fields.push({ id: feature.id });
|
|
151
|
+
}
|
|
152
|
+
indexMap.lineFeature++;
|
|
153
|
+
break;
|
|
154
|
+
case "Polygon":
|
|
155
|
+
handlePolygon(geometry, polygons, indexMap, coordLength, properties);
|
|
156
|
+
polygons.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
157
|
+
if (hasGlobalId) {
|
|
158
|
+
polygons.fields.push({ id: feature.id });
|
|
159
|
+
}
|
|
160
|
+
indexMap.polygonFeature++;
|
|
161
|
+
break;
|
|
162
|
+
default:
|
|
163
|
+
throw new Error("Invalid geometry type");
|
|
164
|
+
}
|
|
165
|
+
indexMap.feature++;
|
|
166
|
+
}
|
|
167
|
+
return makeAccessorObjects(points, lines, polygons, coordLength);
|
|
168
|
+
}
|
|
169
|
+
function handlePoint(geometry, points, indexMap, coordLength, properties) {
|
|
170
|
+
points.positions.set(geometry.data, indexMap.pointPosition * coordLength);
|
|
171
|
+
const nPositions = geometry.data.length / coordLength;
|
|
172
|
+
fillNumericProperties(points, properties, indexMap.pointPosition, nPositions);
|
|
173
|
+
points.globalFeatureIds.fill(
|
|
174
|
+
indexMap.feature,
|
|
175
|
+
indexMap.pointPosition,
|
|
176
|
+
indexMap.pointPosition + nPositions
|
|
177
|
+
);
|
|
178
|
+
points.featureIds.fill(
|
|
179
|
+
indexMap.pointFeature,
|
|
180
|
+
indexMap.pointPosition,
|
|
181
|
+
indexMap.pointPosition + nPositions
|
|
182
|
+
);
|
|
183
|
+
indexMap.pointPosition += nPositions;
|
|
184
|
+
}
|
|
185
|
+
function handleLineString(geometry, lines, indexMap, coordLength, properties) {
|
|
186
|
+
lines.positions.set(geometry.data, indexMap.linePosition * coordLength);
|
|
187
|
+
const nPositions = geometry.data.length / coordLength;
|
|
188
|
+
fillNumericProperties(lines, properties, indexMap.linePosition, nPositions);
|
|
189
|
+
lines.globalFeatureIds.fill(
|
|
190
|
+
indexMap.feature,
|
|
191
|
+
indexMap.linePosition,
|
|
192
|
+
indexMap.linePosition + nPositions
|
|
193
|
+
);
|
|
194
|
+
lines.featureIds.fill(
|
|
195
|
+
indexMap.lineFeature,
|
|
196
|
+
indexMap.linePosition,
|
|
197
|
+
indexMap.linePosition + nPositions
|
|
198
|
+
);
|
|
199
|
+
for (let i = 0, il = geometry.indices.length; i < il; ++i) {
|
|
200
|
+
const start = geometry.indices[i];
|
|
201
|
+
const end = i === il - 1 ? geometry.data.length : geometry.indices[i + 1];
|
|
202
|
+
lines.pathIndices[indexMap.linePath++] = indexMap.linePosition;
|
|
203
|
+
indexMap.linePosition += (end - start) / coordLength;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function handlePolygon(geometry, polygons, indexMap, coordLength, properties) {
|
|
207
|
+
polygons.positions.set(geometry.data, indexMap.polygonPosition * coordLength);
|
|
208
|
+
const nPositions = geometry.data.length / coordLength;
|
|
209
|
+
fillNumericProperties(polygons, properties, indexMap.polygonPosition, nPositions);
|
|
210
|
+
polygons.globalFeatureIds.fill(
|
|
211
|
+
indexMap.feature,
|
|
212
|
+
indexMap.polygonPosition,
|
|
213
|
+
indexMap.polygonPosition + nPositions
|
|
214
|
+
);
|
|
215
|
+
polygons.featureIds.fill(
|
|
216
|
+
indexMap.polygonFeature,
|
|
217
|
+
indexMap.polygonPosition,
|
|
218
|
+
indexMap.polygonPosition + nPositions
|
|
219
|
+
);
|
|
220
|
+
for (let l = 0, ll = geometry.indices.length; l < ll; ++l) {
|
|
221
|
+
const startPosition = indexMap.polygonPosition;
|
|
222
|
+
polygons.polygonIndices[indexMap.polygonObject++] = startPosition;
|
|
223
|
+
const areas = geometry.areas[l];
|
|
224
|
+
const indices = geometry.indices[l];
|
|
225
|
+
const nextIndices = geometry.indices[l + 1];
|
|
226
|
+
for (let i = 0, il = indices.length; i < il; ++i) {
|
|
227
|
+
const start = indices[i];
|
|
228
|
+
const end = i === il - 1 ? (
|
|
229
|
+
// last line, so either read to:
|
|
230
|
+
nextIndices === void 0 ? geometry.data.length : nextIndices[0]
|
|
231
|
+
) : indices[i + 1];
|
|
232
|
+
polygons.primitivePolygonIndices[indexMap.polygonRing++] = indexMap.polygonPosition;
|
|
233
|
+
indexMap.polygonPosition += (end - start) / coordLength;
|
|
234
|
+
}
|
|
235
|
+
const endPosition = indexMap.polygonPosition;
|
|
236
|
+
triangulatePolygon(polygons, areas, indices, { startPosition, endPosition, coordLength });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function triangulatePolygon(polygons, areas, indices, {
|
|
240
|
+
startPosition,
|
|
241
|
+
endPosition,
|
|
242
|
+
coordLength
|
|
243
|
+
}) {
|
|
244
|
+
if (!polygons.triangles) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const start = startPosition * coordLength;
|
|
248
|
+
const end = endPosition * coordLength;
|
|
249
|
+
const polygonPositions = polygons.positions.subarray(start, end);
|
|
250
|
+
const offset = indices[0];
|
|
251
|
+
const holes = indices.slice(1).map((n) => (n - offset) / coordLength);
|
|
252
|
+
const triangles = (0, import_polygon.earcut)(polygonPositions, holes, coordLength, areas);
|
|
253
|
+
for (let t = 0, tl = triangles.length; t < tl; ++t) {
|
|
254
|
+
polygons.triangles.push(startPosition + triangles[t]);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function wrapProps(obj, size) {
|
|
258
|
+
const returnObj = {};
|
|
259
|
+
for (const key in obj) {
|
|
260
|
+
returnObj[key] = { value: obj[key], size };
|
|
261
|
+
}
|
|
262
|
+
return returnObj;
|
|
263
|
+
}
|
|
264
|
+
function makeAccessorObjects(points, lines, polygons, coordLength) {
|
|
265
|
+
const binaryFeatures = {
|
|
266
|
+
points: {
|
|
267
|
+
...points,
|
|
268
|
+
positions: { value: points.positions, size: coordLength },
|
|
269
|
+
globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
|
|
270
|
+
featureIds: { value: points.featureIds, size: 1 },
|
|
271
|
+
numericProps: wrapProps(points.numericProps, 1)
|
|
272
|
+
},
|
|
273
|
+
lines: {
|
|
274
|
+
...lines,
|
|
275
|
+
positions: { value: lines.positions, size: coordLength },
|
|
276
|
+
pathIndices: { value: lines.pathIndices, size: 1 },
|
|
277
|
+
globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
|
|
278
|
+
featureIds: { value: lines.featureIds, size: 1 },
|
|
279
|
+
numericProps: wrapProps(lines.numericProps, 1)
|
|
280
|
+
},
|
|
281
|
+
polygons: {
|
|
282
|
+
...polygons,
|
|
283
|
+
positions: { value: polygons.positions, size: coordLength },
|
|
284
|
+
polygonIndices: { value: polygons.polygonIndices, size: 1 },
|
|
285
|
+
primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
|
|
286
|
+
globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
|
|
287
|
+
featureIds: { value: polygons.featureIds, size: 1 },
|
|
288
|
+
numericProps: wrapProps(polygons.numericProps, 1)
|
|
289
|
+
}
|
|
290
|
+
// triangles not expected
|
|
291
|
+
};
|
|
292
|
+
if (binaryFeatures.polygons && polygons.triangles) {
|
|
293
|
+
binaryFeatures.polygons.triangles = { value: new Uint32Array(polygons.triangles), size: 1 };
|
|
294
|
+
}
|
|
295
|
+
return binaryFeatures;
|
|
296
|
+
}
|
|
297
|
+
function fillNumericProperties(object, properties, index, length) {
|
|
298
|
+
for (const numericPropName in object.numericProps) {
|
|
299
|
+
if (numericPropName in properties) {
|
|
300
|
+
const value = properties[numericPropName];
|
|
301
|
+
object.numericProps[numericPropName].fill(value, index, index + length);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function keepStringProperties(properties, numericKeys) {
|
|
306
|
+
const props = {};
|
|
307
|
+
for (const key in properties) {
|
|
308
|
+
if (!numericKeys.includes(key)) {
|
|
309
|
+
props[key] = properties[key];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return props;
|
|
313
|
+
}
|
|
314
|
+
function deduceArrayType(x, constructor) {
|
|
315
|
+
if (constructor === Array || !Number.isFinite(x)) {
|
|
316
|
+
return Array;
|
|
317
|
+
}
|
|
318
|
+
return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/lib/extract-geometry-info.ts
|
|
322
|
+
function extractGeometryInfo(features) {
|
|
323
|
+
let pointPositionsCount = 0;
|
|
324
|
+
let pointFeaturesCount = 0;
|
|
325
|
+
let linePositionsCount = 0;
|
|
326
|
+
let linePathsCount = 0;
|
|
327
|
+
let lineFeaturesCount = 0;
|
|
328
|
+
let polygonPositionsCount = 0;
|
|
329
|
+
let polygonObjectsCount = 0;
|
|
330
|
+
let polygonRingsCount = 0;
|
|
331
|
+
let polygonFeaturesCount = 0;
|
|
332
|
+
const coordLengths = /* @__PURE__ */ new Set();
|
|
333
|
+
for (const feature of features) {
|
|
334
|
+
const geometry = feature.geometry;
|
|
335
|
+
switch (geometry.type) {
|
|
336
|
+
case "Point":
|
|
337
|
+
pointFeaturesCount++;
|
|
338
|
+
pointPositionsCount++;
|
|
339
|
+
coordLengths.add(geometry.coordinates.length);
|
|
340
|
+
break;
|
|
341
|
+
case "MultiPoint":
|
|
342
|
+
pointFeaturesCount++;
|
|
343
|
+
pointPositionsCount += geometry.coordinates.length;
|
|
344
|
+
for (const point of geometry.coordinates) {
|
|
345
|
+
coordLengths.add(point.length);
|
|
346
|
+
}
|
|
347
|
+
break;
|
|
348
|
+
case "LineString":
|
|
349
|
+
lineFeaturesCount++;
|
|
350
|
+
linePositionsCount += geometry.coordinates.length;
|
|
351
|
+
linePathsCount++;
|
|
352
|
+
for (const coord of geometry.coordinates) {
|
|
353
|
+
coordLengths.add(coord.length);
|
|
354
|
+
}
|
|
355
|
+
break;
|
|
356
|
+
case "MultiLineString":
|
|
357
|
+
lineFeaturesCount++;
|
|
358
|
+
for (const line of geometry.coordinates) {
|
|
359
|
+
linePositionsCount += line.length;
|
|
360
|
+
linePathsCount++;
|
|
361
|
+
for (const coord of line) {
|
|
362
|
+
coordLengths.add(coord.length);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
break;
|
|
366
|
+
case "Polygon":
|
|
367
|
+
polygonFeaturesCount++;
|
|
368
|
+
polygonObjectsCount++;
|
|
369
|
+
polygonRingsCount += geometry.coordinates.length;
|
|
370
|
+
const flattened = geometry.coordinates.flat();
|
|
371
|
+
polygonPositionsCount += flattened.length;
|
|
372
|
+
for (const coord of flattened) {
|
|
373
|
+
coordLengths.add(coord.length);
|
|
374
|
+
}
|
|
375
|
+
break;
|
|
376
|
+
case "MultiPolygon":
|
|
377
|
+
polygonFeaturesCount++;
|
|
378
|
+
for (const polygon of geometry.coordinates) {
|
|
379
|
+
polygonObjectsCount++;
|
|
380
|
+
polygonRingsCount += polygon.length;
|
|
381
|
+
const flattened2 = polygon.flat();
|
|
382
|
+
polygonPositionsCount += flattened2.length;
|
|
383
|
+
for (const coord of flattened2) {
|
|
384
|
+
coordLengths.add(coord.length);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
break;
|
|
388
|
+
default:
|
|
389
|
+
throw new Error(`Unsupported geometry type: ${geometry.type}`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
|
|
394
|
+
pointPositionsCount,
|
|
395
|
+
pointFeaturesCount,
|
|
396
|
+
linePositionsCount,
|
|
397
|
+
linePathsCount,
|
|
398
|
+
lineFeaturesCount,
|
|
399
|
+
polygonPositionsCount,
|
|
400
|
+
polygonObjectsCount,
|
|
401
|
+
polygonRingsCount,
|
|
402
|
+
polygonFeaturesCount
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/lib/geojson-to-flat-geojson.ts
|
|
407
|
+
var import_polygon2 = require("@math.gl/polygon");
|
|
408
|
+
function geojsonToFlatGeojson(features, options = { coordLength: 2, fixRingWinding: true }) {
|
|
409
|
+
return features.map((feature) => flattenFeature(feature, options));
|
|
410
|
+
}
|
|
411
|
+
function flattenPoint(coordinates, data, indices, options) {
|
|
412
|
+
indices.push(data.length);
|
|
413
|
+
data.push(...coordinates);
|
|
414
|
+
for (let i = coordinates.length; i < options.coordLength; i++) {
|
|
415
|
+
data.push(0);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function flattenLineString(coordinates, data, indices, options) {
|
|
419
|
+
indices.push(data.length);
|
|
420
|
+
for (const c of coordinates) {
|
|
421
|
+
data.push(...c);
|
|
422
|
+
for (let i = c.length; i < options.coordLength; i++) {
|
|
423
|
+
data.push(0);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function flattenPolygon(coordinates, data, indices, areas, options) {
|
|
428
|
+
let count = 0;
|
|
429
|
+
const ringAreas = [];
|
|
430
|
+
const polygons = [];
|
|
431
|
+
for (const lineString of coordinates) {
|
|
432
|
+
const lineString2d = lineString.map((p) => p.slice(0, 2));
|
|
433
|
+
let area = (0, import_polygon2.getPolygonSignedArea)(lineString2d.flat());
|
|
434
|
+
const ccw = area < 0;
|
|
435
|
+
if (options.fixRingWinding && (count === 0 && !ccw || count > 0 && ccw)) {
|
|
436
|
+
lineString.reverse();
|
|
437
|
+
area = -area;
|
|
438
|
+
}
|
|
439
|
+
ringAreas.push(area);
|
|
440
|
+
flattenLineString(lineString, data, polygons, options);
|
|
441
|
+
count++;
|
|
442
|
+
}
|
|
443
|
+
if (count > 0) {
|
|
444
|
+
areas.push(ringAreas);
|
|
445
|
+
indices.push(polygons);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
function flattenFeature(feature, options) {
|
|
449
|
+
const { geometry } = feature;
|
|
450
|
+
if (geometry.type === "GeometryCollection") {
|
|
451
|
+
throw new Error("GeometryCollection type not supported");
|
|
452
|
+
}
|
|
453
|
+
const data = [];
|
|
454
|
+
const indices = [];
|
|
455
|
+
let areas;
|
|
456
|
+
let type;
|
|
457
|
+
switch (geometry.type) {
|
|
458
|
+
case "Point":
|
|
459
|
+
type = "Point";
|
|
460
|
+
flattenPoint(geometry.coordinates, data, indices, options);
|
|
461
|
+
break;
|
|
462
|
+
case "MultiPoint":
|
|
463
|
+
type = "Point";
|
|
464
|
+
geometry.coordinates.map((c) => flattenPoint(c, data, indices, options));
|
|
465
|
+
break;
|
|
466
|
+
case "LineString":
|
|
467
|
+
type = "LineString";
|
|
468
|
+
flattenLineString(geometry.coordinates, data, indices, options);
|
|
469
|
+
break;
|
|
470
|
+
case "MultiLineString":
|
|
471
|
+
type = "LineString";
|
|
472
|
+
geometry.coordinates.map((c) => flattenLineString(c, data, indices, options));
|
|
473
|
+
break;
|
|
474
|
+
case "Polygon":
|
|
475
|
+
type = "Polygon";
|
|
476
|
+
areas = [];
|
|
477
|
+
flattenPolygon(geometry.coordinates, data, indices, areas, options);
|
|
478
|
+
break;
|
|
479
|
+
case "MultiPolygon":
|
|
480
|
+
type = "Polygon";
|
|
481
|
+
areas = [];
|
|
482
|
+
geometry.coordinates.map((c) => flattenPolygon(c, data, indices, areas, options));
|
|
483
|
+
break;
|
|
484
|
+
default:
|
|
485
|
+
throw new Error(`Unknown type: ${type}`);
|
|
486
|
+
}
|
|
487
|
+
return { ...feature, geometry: { type, indices, data, areas } };
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// src/lib/geojson-to-binary.ts
|
|
491
|
+
function geojsonToBinary(features, options = { fixRingWinding: true, triangulate: true }) {
|
|
492
|
+
const geometryInfo = extractGeometryInfo(features);
|
|
493
|
+
const coordLength = geometryInfo.coordLength;
|
|
494
|
+
const { fixRingWinding } = options;
|
|
495
|
+
const flatFeatures = geojsonToFlatGeojson(features, { coordLength, fixRingWinding });
|
|
496
|
+
return flatGeojsonToBinary(flatFeatures, geometryInfo, {
|
|
497
|
+
numericPropKeys: options.numericPropKeys,
|
|
498
|
+
PositionDataType: options.PositionDataType || Float32Array,
|
|
499
|
+
triangulate: options.triangulate
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// src/lib/binary-to-geojson.ts
|
|
504
|
+
function binaryToGeojson(data, options) {
|
|
505
|
+
const globalFeatureId = options == null ? void 0 : options.globalFeatureId;
|
|
506
|
+
if (globalFeatureId !== void 0) {
|
|
507
|
+
return getSingleFeature(data, globalFeatureId);
|
|
508
|
+
}
|
|
509
|
+
return parseFeatures(data, options == null ? void 0 : options.type);
|
|
510
|
+
}
|
|
511
|
+
function getSingleFeature(data, globalFeatureId) {
|
|
512
|
+
const dataArray = normalizeInput(data);
|
|
513
|
+
for (const data2 of dataArray) {
|
|
514
|
+
let lastIndex = 0;
|
|
515
|
+
let lastValue = data2.featureIds.value[0];
|
|
516
|
+
for (let i = 0; i < data2.featureIds.value.length; i++) {
|
|
517
|
+
const currValue = data2.featureIds.value[i];
|
|
518
|
+
if (currValue === lastValue) {
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
if (globalFeatureId === data2.globalFeatureIds.value[lastIndex]) {
|
|
522
|
+
return parseFeature(data2, lastIndex, i);
|
|
523
|
+
}
|
|
524
|
+
lastIndex = i;
|
|
525
|
+
lastValue = currValue;
|
|
526
|
+
}
|
|
527
|
+
if (globalFeatureId === data2.globalFeatureIds.value[lastIndex]) {
|
|
528
|
+
return parseFeature(data2, lastIndex, data2.featureIds.value.length);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
throw new Error(`featureId:${globalFeatureId} not found`);
|
|
532
|
+
}
|
|
533
|
+
function parseFeatures(data, type) {
|
|
534
|
+
const dataArray = normalizeInput(data, type);
|
|
535
|
+
return parseFeatureCollection(dataArray);
|
|
536
|
+
}
|
|
537
|
+
function binaryToGeometry(data, startIndex, endIndex) {
|
|
538
|
+
switch (data.type) {
|
|
539
|
+
case "Point":
|
|
540
|
+
return pointToGeoJson(data, startIndex, endIndex);
|
|
541
|
+
case "LineString":
|
|
542
|
+
return lineStringToGeoJson(data, startIndex, endIndex);
|
|
543
|
+
case "Polygon":
|
|
544
|
+
return polygonToGeoJson(data, startIndex, endIndex);
|
|
545
|
+
default:
|
|
546
|
+
const unexpectedInput = data;
|
|
547
|
+
throw new Error(`Unsupported geometry type: ${unexpectedInput == null ? void 0 : unexpectedInput.type}`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
function normalizeInput(data, type) {
|
|
551
|
+
const features = [];
|
|
552
|
+
if (data.points) {
|
|
553
|
+
data.points.type = "Point";
|
|
554
|
+
features.push(data.points);
|
|
555
|
+
}
|
|
556
|
+
if (data.lines) {
|
|
557
|
+
data.lines.type = "LineString";
|
|
558
|
+
features.push(data.lines);
|
|
559
|
+
}
|
|
560
|
+
if (data.polygons) {
|
|
561
|
+
data.polygons.type = "Polygon";
|
|
562
|
+
features.push(data.polygons);
|
|
563
|
+
}
|
|
564
|
+
return features;
|
|
565
|
+
}
|
|
566
|
+
function parseFeatureCollection(dataArray) {
|
|
567
|
+
const features = [];
|
|
568
|
+
for (const data of dataArray) {
|
|
569
|
+
if (data.featureIds.value.length === 0) {
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
let lastIndex = 0;
|
|
573
|
+
let lastValue = data.featureIds.value[0];
|
|
574
|
+
for (let i = 0; i < data.featureIds.value.length; i++) {
|
|
575
|
+
const currValue = data.featureIds.value[i];
|
|
576
|
+
if (currValue === lastValue) {
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
features.push(parseFeature(data, lastIndex, i));
|
|
580
|
+
lastIndex = i;
|
|
581
|
+
lastValue = currValue;
|
|
582
|
+
}
|
|
583
|
+
features.push(parseFeature(data, lastIndex, data.featureIds.value.length));
|
|
584
|
+
}
|
|
585
|
+
return features;
|
|
586
|
+
}
|
|
587
|
+
function parseFeature(data, startIndex, endIndex) {
|
|
588
|
+
const geometry = binaryToGeometry(data, startIndex, endIndex);
|
|
589
|
+
const properties = parseProperties(data, startIndex, endIndex);
|
|
590
|
+
const fields = parseFields(data, startIndex, endIndex);
|
|
591
|
+
return { type: "Feature", geometry, properties, ...fields };
|
|
592
|
+
}
|
|
593
|
+
function parseFields(data, startIndex = 0, endIndex) {
|
|
594
|
+
return data.fields && data.fields[data.featureIds.value[startIndex]];
|
|
595
|
+
}
|
|
596
|
+
function parseProperties(data, startIndex = 0, endIndex) {
|
|
597
|
+
const properties = Object.assign({}, data.properties[data.featureIds.value[startIndex]]);
|
|
598
|
+
for (const key in data.numericProps) {
|
|
599
|
+
properties[key] = data.numericProps[key].value[startIndex];
|
|
600
|
+
}
|
|
601
|
+
return properties;
|
|
602
|
+
}
|
|
603
|
+
function polygonToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
|
|
604
|
+
const { positions } = data;
|
|
605
|
+
const polygonIndices = data.polygonIndices.value.filter((x) => x >= startIndex && x <= endIndex);
|
|
606
|
+
const primitivePolygonIndices = data.primitivePolygonIndices.value.filter(
|
|
607
|
+
(x) => x >= startIndex && x <= endIndex
|
|
608
|
+
);
|
|
609
|
+
const multi = polygonIndices.length > 2;
|
|
610
|
+
if (!multi) {
|
|
611
|
+
const coordinates2 = [];
|
|
612
|
+
for (let i = 0; i < primitivePolygonIndices.length - 1; i++) {
|
|
613
|
+
const startRingIndex = primitivePolygonIndices[i];
|
|
614
|
+
const endRingIndex = primitivePolygonIndices[i + 1];
|
|
615
|
+
const ringCoordinates = ringToGeoJson(positions, startRingIndex, endRingIndex);
|
|
616
|
+
coordinates2.push(ringCoordinates);
|
|
617
|
+
}
|
|
618
|
+
return { type: "Polygon", coordinates: coordinates2 };
|
|
619
|
+
}
|
|
620
|
+
const coordinates = [];
|
|
621
|
+
for (let i = 0; i < polygonIndices.length - 1; i++) {
|
|
622
|
+
const startPolygonIndex = polygonIndices[i];
|
|
623
|
+
const endPolygonIndex = polygonIndices[i + 1];
|
|
624
|
+
const polygonCoordinates = polygonToGeoJson(
|
|
625
|
+
data,
|
|
626
|
+
startPolygonIndex,
|
|
627
|
+
endPolygonIndex
|
|
628
|
+
).coordinates;
|
|
629
|
+
coordinates.push(polygonCoordinates);
|
|
630
|
+
}
|
|
631
|
+
return { type: "MultiPolygon", coordinates };
|
|
632
|
+
}
|
|
633
|
+
function lineStringToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
|
|
634
|
+
const { positions } = data;
|
|
635
|
+
const pathIndices = data.pathIndices.value.filter((x) => x >= startIndex && x <= endIndex);
|
|
636
|
+
const multi = pathIndices.length > 2;
|
|
637
|
+
if (!multi) {
|
|
638
|
+
const coordinates2 = ringToGeoJson(positions, pathIndices[0], pathIndices[1]);
|
|
639
|
+
return { type: "LineString", coordinates: coordinates2 };
|
|
640
|
+
}
|
|
641
|
+
const coordinates = [];
|
|
642
|
+
for (let i = 0; i < pathIndices.length - 1; i++) {
|
|
643
|
+
const ringCoordinates = ringToGeoJson(positions, pathIndices[i], pathIndices[i + 1]);
|
|
644
|
+
coordinates.push(ringCoordinates);
|
|
645
|
+
}
|
|
646
|
+
return { type: "MultiLineString", coordinates };
|
|
647
|
+
}
|
|
648
|
+
function pointToGeoJson(data, startIndex, endIndex) {
|
|
649
|
+
const { positions } = data;
|
|
650
|
+
const coordinates = ringToGeoJson(positions, startIndex, endIndex);
|
|
651
|
+
const multi = coordinates.length > 1;
|
|
652
|
+
if (multi) {
|
|
653
|
+
return { type: "MultiPoint", coordinates };
|
|
654
|
+
}
|
|
655
|
+
return { type: "Point", coordinates: coordinates[0] };
|
|
656
|
+
}
|
|
657
|
+
function ringToGeoJson(positions, startIndex, endIndex) {
|
|
658
|
+
startIndex = startIndex || 0;
|
|
659
|
+
endIndex = endIndex || positions.value.length / positions.size;
|
|
660
|
+
const ringCoordinates = [];
|
|
661
|
+
for (let j = startIndex; j < endIndex; j++) {
|
|
662
|
+
const coord = Array();
|
|
663
|
+
for (let k = j * positions.size; k < (j + 1) * positions.size; k++) {
|
|
664
|
+
coord.push(Number(positions.value[k]));
|
|
665
|
+
}
|
|
666
|
+
ringCoordinates.push(coord);
|
|
667
|
+
}
|
|
668
|
+
return ringCoordinates;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/lib/transform.ts
|
|
672
|
+
function transformBinaryCoords(binaryFeatures, transformCoordinate) {
|
|
673
|
+
if (binaryFeatures.points) {
|
|
674
|
+
transformBinaryGeometryPositions(binaryFeatures.points, transformCoordinate);
|
|
675
|
+
}
|
|
676
|
+
if (binaryFeatures.lines) {
|
|
677
|
+
transformBinaryGeometryPositions(binaryFeatures.lines, transformCoordinate);
|
|
678
|
+
}
|
|
679
|
+
if (binaryFeatures.polygons) {
|
|
680
|
+
transformBinaryGeometryPositions(binaryFeatures.polygons, transformCoordinate);
|
|
681
|
+
}
|
|
682
|
+
return binaryFeatures;
|
|
683
|
+
}
|
|
684
|
+
function transformBinaryGeometryPositions(binaryGeometry, fn) {
|
|
685
|
+
const { positions } = binaryGeometry;
|
|
686
|
+
for (let i = 0; i < positions.value.length; i += positions.size) {
|
|
687
|
+
const coord = Array.from(positions.value.subarray(i, i + positions.size));
|
|
688
|
+
const transformedCoord = fn(coord);
|
|
689
|
+
positions.value.set(transformedCoord, i);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function transformGeoJsonCoords(features, fn) {
|
|
693
|
+
for (const feature of features) {
|
|
694
|
+
feature.geometry.coordinates = coordMap(feature.geometry.coordinates, fn);
|
|
695
|
+
}
|
|
696
|
+
return features;
|
|
697
|
+
}
|
|
698
|
+
function coordMap(array, fn) {
|
|
699
|
+
if (isCoord(array)) {
|
|
700
|
+
return fn(array);
|
|
701
|
+
}
|
|
702
|
+
return array.map((item) => {
|
|
703
|
+
return coordMap(item, fn);
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
function isCoord(array) {
|
|
707
|
+
return Array.isArray(array) && Number.isFinite(array[0]) && Number.isFinite(array[1]);
|
|
708
|
+
}
|