@loaders.gl/flatgeobuf 4.3.0-alpha.2 → 4.3.0-alpha.4

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.
@@ -1,6 +1,14 @@
1
- import type { FlatGeobufLoaderOptions } from "../flatgeobuf-loader.js";
2
1
  import type { Table } from '@loaders.gl/schema';
3
2
  import * as fgb from '../flatgeobuf/3.27.2';
4
- export declare function parseFlatGeobuf(arrayBuffer: ArrayBuffer, options?: FlatGeobufLoaderOptions): Table;
5
- export declare function parseFlatGeobufInBatches(stream: any, options: FlatGeobufLoaderOptions): any[] | AsyncGenerator<fgb.IFeature, any, unknown> | AsyncGenerator<any, void, unknown>;
3
+ export type ParseFlatGeobufOptions = {
4
+ shape?: 'geojson-table' | 'columnar-table' | 'binary';
5
+ /** If supplied, only loads features within the bounding box */
6
+ boundingBox?: [[number, number], [number, number]];
7
+ /** Desired output CRS */
8
+ crs?: string;
9
+ /** Should geometries be reprojected to target CRS */
10
+ reproject?: boolean;
11
+ };
12
+ export declare function parseFlatGeobuf(arrayBuffer: ArrayBuffer, options: ParseFlatGeobufOptions): Table;
13
+ export declare function parseFlatGeobufInBatches(stream: any, options: ParseFlatGeobufOptions): any[] | AsyncGenerator<fgb.IFeature, any, unknown> | AsyncGenerator<any, void, unknown>;
6
14
  //# sourceMappingURL=parse-flatgeobuf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-flatgeobuf.d.ts","sourceRoot":"","sources":["../../src/lib/parse-flatgeobuf.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,uBAAuB,EAAC,gCAA6B;AAClE,OAAO,KAAK,EAAe,KAAK,EAAS,MAAM,oBAAoB,CAAC;AAKpE,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAC;AAgC5C,wBAAgB,eAAe,CAC7B,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,uBAAuB,GAChC,KAAK,CAoBP;AAyDD,wBAAgB,wBAAwB,CAAC,MAAM,KAAA,EAAE,OAAO,EAAE,uBAAuB,2FAUhF"}
1
+ {"version":3,"file":"parse-flatgeobuf.d.ts","sourceRoot":"","sources":["../../src/lib/parse-flatgeobuf.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAe,KAAK,EAAS,MAAM,oBAAoB,CAAC;AAKpE,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAC;AAS5C,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,CAAC,EAAE,eAAe,GAAG,gBAAgB,GAAG,QAAQ,CAAC;IACtD,+DAA+D;IAC/D,WAAW,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAQF,wBAAgB,eAAe,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,GAAG,KAAK,CAoBhG;AA2DD,wBAAgB,wBAAwB,CAAC,MAAM,KAAA,EAAE,OAAO,EAAE,sBAAsB,2FAU/E"}
@@ -10,21 +10,6 @@ import * as generic from "../flatgeobuf/3.27.2/generic.js";
10
10
  import { parseProperties as parsePropertiesBinary } from "../flatgeobuf/3.27.2/generic/feature.js";
11
11
  const deserializeGeoJson = geojson.deserialize;
12
12
  const deserializeGeneric = generic.deserialize;
13
- // const parsePropertiesBinary = FlatgeobufFeature.parseProperties;
14
- // TODO: reproject binary features
15
- function binaryFromFeature(feature, header) {
16
- const geometry = feature.geometry();
17
- // FlatGeobuf files can only hold a single geometry type per file, otherwise
18
- // GeometryType is GeometryCollection
19
- // I believe geometry.type() is null (0) except when the geometry type isn't
20
- // known in the header?
21
- const geometryType = header.geometryType || geometry?.type();
22
- const parsedGeometry = fgbToBinaryGeometry(geometry, geometryType);
23
- // @ts-expect-error this looks wrong
24
- parsedGeometry.properties = parsePropertiesBinary(feature, header.columns);
25
- // TODO: wrap binary data either in points, lines, or polygons key
26
- return parsedGeometry;
27
- }
28
13
  /*
29
14
  * Parse FlatGeobuf arrayBuffer and return GeoJSON.
30
15
  *
@@ -32,7 +17,7 @@ function binaryFromFeature(feature, header) {
32
17
  * @return A GeoJSON geometry object
33
18
  */
34
19
  export function parseFlatGeobuf(arrayBuffer, options) {
35
- const shape = options?.flatgeobuf?.shape;
20
+ const shape = options.shape;
36
21
  switch (shape) {
37
22
  case 'geojson-table': {
38
23
  return parseFlatGeobufToGeoJSONTable(arrayBuffer, options);
@@ -55,27 +40,28 @@ function parseFlatGeobufToBinary(arrayBuffer, options = {}) {
55
40
  // @ts-expect-error
56
41
  return deserializeGeneric(array, fgbToBinaryGeometry);
57
42
  }
58
- function parseFlatGeobufToGeoJSONTable(arrayBuffer, options = {}) {
43
+ function parseFlatGeobufToGeoJSONTable(arrayBuffer, options) {
59
44
  if (arrayBuffer.byteLength === 0) {
60
45
  return { shape: 'geojson-table', type: 'FeatureCollection', features: [] };
61
46
  }
62
- const { reproject = false, _targetCrs = 'WGS84' } = (options && options.gis) || {};
47
+ const { reproject = false, crs = 'WGS84' } = options;
63
48
  const arr = new Uint8Array(arrayBuffer);
64
49
  let fgbHeader;
65
50
  let schema;
51
+ const rect = options.boundingBox && convertBoundingBox(options.boundingBox);
66
52
  // @ts-expect-error this looks wrong
67
- let { features } = deserializeGeoJson(arr, undefined, (headerMeta) => {
53
+ let { features } = deserializeGeoJson(arr, rect, (headerMeta) => {
68
54
  fgbHeader = headerMeta;
69
55
  schema = getSchemaFromFGBHeader(fgbHeader);
70
56
  });
71
- const crs = fgbHeader && fgbHeader.crs;
57
+ const fromCRS = fgbHeader?.crs?.wkt;
72
58
  let projection;
73
- if (reproject && crs) {
59
+ if (reproject && fromCRS) {
74
60
  // Constructing the projection may fail for some invalid WKT strings
75
61
  try {
76
- projection = new Proj4Projection({ from: crs.wkt, to: _targetCrs });
62
+ projection = new Proj4Projection({ from: fromCRS, to: crs });
77
63
  }
78
- catch (e) {
64
+ catch (error) {
79
65
  // no op
80
66
  }
81
67
  }
@@ -92,7 +78,7 @@ function parseFlatGeobufToGeoJSONTable(arrayBuffer, options = {}) {
92
78
  */
93
79
  // eslint-disable-next-line complexity
94
80
  export function parseFlatGeobufInBatches(stream, options) {
95
- const shape = options.flatgeobuf?.shape;
81
+ const shape = options.shape;
96
82
  switch (shape) {
97
83
  case 'binary':
98
84
  return parseFlatGeobufInBatchesToBinary(stream, options);
@@ -105,8 +91,9 @@ export function parseFlatGeobufInBatches(stream, options) {
105
91
  function parseFlatGeobufInBatchesToBinary(stream, options) {
106
92
  // TODO: reproject binary streaming features
107
93
  // const {reproject = false, _targetCrs = 'WGS84'} = (options && options.gis) || {};
94
+ const rect = options.boundingBox && convertBoundingBox(options.boundingBox);
108
95
  // @ts-expect-error
109
- const iterator = deserializeGeneric(stream, binaryFromFeature);
96
+ const iterator = deserializeGeneric(stream, binaryFromFeature, rect);
110
97
  return iterator;
111
98
  }
112
99
  /**
@@ -116,7 +103,7 @@ function parseFlatGeobufInBatchesToBinary(stream, options) {
116
103
  */
117
104
  // eslint-disable-next-line complexity
118
105
  async function* parseFlatGeobufInBatchesToGeoJSON(stream, options) {
119
- const { reproject = false, _targetCrs = 'WGS84' } = (options && options.gis) || {};
106
+ const { reproject = false, crs = 'WGS84' } = options || {};
120
107
  let fgbHeader;
121
108
  // let schema: Schema | undefined;
122
109
  const iterator = deserializeGeoJson(stream, undefined, (headerMeta) => {
@@ -128,9 +115,9 @@ async function* parseFlatGeobufInBatchesToGeoJSON(stream, options) {
128
115
  // @ts-expect-error this looks wrong
129
116
  for await (const feature of iterator) {
130
117
  if (firstRecord) {
131
- const crs = fgbHeader && fgbHeader.crs;
132
- if (reproject && crs) {
133
- projection = new Proj4Projection({ from: crs.wkt, to: _targetCrs });
118
+ const fromCRS = fgbHeader?.crs?.wkt;
119
+ if (reproject && fromCRS) {
120
+ projection = new Proj4Projection({ from: fromCRS, to: crs });
134
121
  }
135
122
  firstRecord = false;
136
123
  }
@@ -143,3 +130,26 @@ async function* parseFlatGeobufInBatchesToGeoJSON(stream, options) {
143
130
  }
144
131
  }
145
132
  }
133
+ // HELPERS
134
+ function convertBoundingBox(boundingBox) {
135
+ return {
136
+ minX: boundingBox[0][0],
137
+ minY: boundingBox[0][1],
138
+ maxX: boundingBox[1][0],
139
+ maxY: boundingBox[1][1]
140
+ };
141
+ }
142
+ // TODO: reproject binary features
143
+ function binaryFromFeature(feature, header) {
144
+ const geometry = feature.geometry();
145
+ // FlatGeobuf files can only hold a single geometry type per file, otherwise
146
+ // GeometryType is GeometryCollection
147
+ // I believe geometry.type() is null (0) except when the geometry type isn't
148
+ // known in the header?
149
+ const geometryType = header.geometryType || geometry?.type();
150
+ const parsedGeometry = fgbToBinaryGeometry(geometry, geometryType);
151
+ // @ts-expect-error this looks wrong
152
+ parsedGeometry.properties = parsePropertiesBinary(feature, header.columns);
153
+ // TODO: wrap binary data either in points, lines, or polygons key
154
+ return parsedGeometry;
155
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loaders.gl/flatgeobuf",
3
3
  "description": "Loader for FlatGeobuf",
4
- "version": "4.3.0-alpha.2",
4
+ "version": "4.3.0-alpha.4",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "publishConfig": {
@@ -44,9 +44,9 @@
44
44
  "build-worker": "esbuild src/workers/flatgeobuf-worker.ts --bundle --outfile=dist/flatgeobuf-worker.js --define:__VERSION__=\\\"$npm_package_version\\\""
45
45
  },
46
46
  "dependencies": {
47
- "@loaders.gl/gis": "4.3.0-alpha.2",
48
- "@loaders.gl/loader-utils": "4.3.0-alpha.2",
49
- "@loaders.gl/schema": "4.3.0-alpha.2",
47
+ "@loaders.gl/gis": "4.3.0-alpha.4",
48
+ "@loaders.gl/loader-utils": "4.3.0-alpha.4",
49
+ "@loaders.gl/schema": "4.3.0-alpha.4",
50
50
  "@math.gl/proj4": "^4.0.0",
51
51
  "flatgeobuf": "3.27.2"
52
52
  },
@@ -56,5 +56,5 @@
56
56
  "peerDependencies": {
57
57
  "@loaders.gl/core": "^4.0.0"
58
58
  },
59
- "gitHead": "77a3cb538ab7a1fbf74245f25590210451689f5c"
59
+ "gitHead": "4900ac4c4de20366c050b80cef04dc5b52d167af"
60
60
  }
@@ -2,8 +2,13 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
+ import type {GeoJSONTable, BinaryFeatureCollection} from '@loaders.gl/schema';
5
6
  import type {Loader, LoaderWithParser, LoaderOptions} from '@loaders.gl/loader-utils';
6
- import {parseFlatGeobuf, parseFlatGeobufInBatches} from './lib/parse-flatgeobuf';
7
+ import {
8
+ parseFlatGeobuf,
9
+ parseFlatGeobufInBatches,
10
+ ParseFlatGeobufOptions
11
+ } from './lib/parse-flatgeobuf';
7
12
 
8
13
  // __VERSION__ is injected by babel-plugin-version-inline
9
14
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
@@ -17,6 +22,7 @@ export type FlatGeobufLoaderOptions = LoaderOptions & {
17
22
  shape?: 'geojson-table' | 'columnar-table' | 'binary';
18
23
  /** Override the URL to the worker bundle (by default loads from unpkg.com) */
19
24
  workerUrl?: string;
25
+ boundingBox?: [[number, number], [number, number]];
20
26
  };
21
27
  gis?: {
22
28
  reproject?: boolean;
@@ -24,6 +30,7 @@ export type FlatGeobufLoaderOptions = LoaderOptions & {
24
30
  };
25
31
  };
26
32
 
33
+ /** Load flatgeobuf on a worker */
27
34
  export const FlatGeobufWorkerLoader = {
28
35
  dataType: null as any,
29
36
  batchType: null as any,
@@ -45,13 +52,36 @@ export const FlatGeobufWorkerLoader = {
45
52
  reproject: false
46
53
  }
47
54
  }
48
- } as const satisfies Loader<any, any, FlatGeobufLoaderOptions>;
55
+ } as const satisfies Loader<GeoJSONTable | BinaryFeatureCollection, any, FlatGeobufLoaderOptions>;
49
56
 
50
57
  export const FlatGeobufLoader = {
51
58
  ...FlatGeobufWorkerLoader,
52
- parse: async (arrayBuffer, options) => parseFlatGeobuf(arrayBuffer, options),
53
- parseSync: parseFlatGeobuf,
59
+ parse: async (arrayBuffer: ArrayBuffer, options: FlatGeobufLoaderOptions = {}) =>
60
+ parseSync(arrayBuffer, options),
61
+ parseSync,
54
62
  // @ts-expect-error this is a stream parser not an async iterator parser
55
- parseInBatchesFromStream: parseFlatGeobufInBatches,
63
+ parseInBatchesFromStream,
56
64
  binary: true
57
65
  } as const satisfies LoaderWithParser<any, any, FlatGeobufLoaderOptions>;
66
+
67
+ function parseSync(arrayBuffer: ArrayBuffer, options: FlatGeobufLoaderOptions = {}) {
68
+ return parseFlatGeobuf(arrayBuffer, getOptions(options));
69
+ }
70
+
71
+ function parseInBatchesFromStream(stream: any, options: FlatGeobufLoaderOptions) {
72
+ return parseFlatGeobufInBatches(stream, getOptions(options));
73
+ }
74
+
75
+ function getOptions(options: FlatGeobufLoaderOptions): ParseFlatGeobufOptions {
76
+ options = {
77
+ ...options,
78
+ flatgeobuf: {...FlatGeobufLoader.options.flatgeobuf, ...options?.flatgeobuf},
79
+ gis: {...FlatGeobufLoader.options.gis, ...options?.gis}
80
+ };
81
+ return {
82
+ shape: options?.flatgeobuf?.shape ?? 'geojson-table',
83
+ boundingBox: options?.flatgeobuf?.boundingBox,
84
+ crs: options?.gis?._targetCrs || 'WGS84',
85
+ reproject: options?.gis?.reproject || false
86
+ };
87
+ }
@@ -0,0 +1,100 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {Schema, GeoJSONTable} from '@loaders.gl/schema';
6
+ import type {
7
+ VectorSourceProps,
8
+ VectorSourceMetadata,
9
+ GetFeaturesParameters,
10
+ LoaderWithParser
11
+ } from '@loaders.gl/loader-utils';
12
+ import {Source, VectorSource} from '@loaders.gl/loader-utils';
13
+
14
+ import {FlatGeobufLoader} from './flatgeobuf-loader';
15
+
16
+ /**
17
+ * @ndeprecated This is a WIP, not fully implemented
18
+ * @see https://developers.arcgis.com/rest/services-reference/enterprise/feature-service.htm
19
+ */
20
+ export const FlatGeobufSource = {
21
+ name: 'FlatGeobuf',
22
+ id: 'flatgeobuf-server',
23
+ module: 'wms',
24
+ version: '0.0.0',
25
+ extensions: [],
26
+ mimeTypes: [],
27
+ options: {
28
+ url: undefined!,
29
+ 'flatgeobuf-server': {
30
+ /** Tabular loaders, normally the GeoJSONLoader */
31
+ loaders: []
32
+ }
33
+ },
34
+
35
+ type: 'flatgeobuf-server',
36
+ fromUrl: true,
37
+ fromBlob: false, // TODO check if supported by library?
38
+
39
+ testURL: (url: string): boolean => url.toLowerCase().includes('FeatureServer'),
40
+ createDataSource: (url, props: FlatGeobufVectorSourceProps): FlatGeobufVectorSource =>
41
+ new FlatGeobufVectorSource(props)
42
+ } as const satisfies Source<FlatGeobufVectorSource, FlatGeobufVectorSourceProps>;
43
+
44
+ export type FlatGeobufVectorSourceProps = VectorSourceProps & {
45
+ url: string;
46
+ 'flatgeobuf-server'?: {
47
+ loaders: LoaderWithParser[];
48
+ };
49
+ };
50
+
51
+ /**
52
+ * ArcGIS ImageServer
53
+ * Note - exports a big API, that could be exposed here if there is a use case
54
+ * @see https://developers.arcgis.com/rest/services-reference/enterprise/feature-service.htm
55
+ */
56
+ export class FlatGeobufVectorSource extends VectorSource<FlatGeobufVectorSourceProps> {
57
+ data: string;
58
+ url: string;
59
+ protected formatSpecificMetadata: Promise<any> | null = null;
60
+
61
+ constructor(props: FlatGeobufVectorSourceProps) {
62
+ super(props);
63
+ this.data = props.url;
64
+ this.url = props.url;
65
+ // this.formatSpecificMetadata = this._getFormatSpecificMetadata();
66
+ }
67
+
68
+ /** TODO - not yet clear if we can find schema information in the FeatureServer metadata or if we need to request a feature */
69
+ async getSchema(): Promise<Schema> {
70
+ await this.getMetadata({formatSpecificMetadata: true});
71
+ return {metadata: {}, fields: []};
72
+ }
73
+
74
+ async getMetadata(options: {formatSpecificMetadata}): Promise<VectorSourceMetadata> {
75
+ // Wait for raw metadata to load
76
+ if (!this.formatSpecificMetadata) {
77
+ // this.formatSpecificMetadata = await this._getFormatSpecificMetadata();
78
+ }
79
+
80
+ // const metadata = parseFlatGeobufMetadata(this.formatSpecificMetadata);
81
+
82
+ // Only add the big blob of source metadata if explicitly requested
83
+ if (options.formatSpecificMetadata) {
84
+ // metadata.formatSpecificMetadata = this.formatSpecificMetadata;
85
+ }
86
+ // @ts-expect-error
87
+ return {};
88
+ }
89
+
90
+ async getFeatures(parameters: GetFeaturesParameters): Promise<GeoJSONTable> {
91
+ const response = await this.fetch(this.url);
92
+ const arrayBuffer = await response.arrayBuffer();
93
+ // TODO - hack - done to avoid pulling in selectLoader from core
94
+
95
+ const table = await FlatGeobufLoader.parse(arrayBuffer, {});
96
+ // const loader = this.props['flatgeobuf-server']?.loaders?.[0];
97
+ // const table = loader?.parse(arrayBuffer);
98
+ return table as GeoJSONTable;
99
+ }
100
+ }
@@ -5,7 +5,6 @@
5
5
  import {Proj4Projection} from '@math.gl/proj4';
6
6
  import {transformGeoJsonCoords} from '@loaders.gl/gis';
7
7
 
8
- import type {FlatGeobufLoaderOptions} from '../flatgeobuf-loader';
9
8
  import type {GeoJSONTable, Table, Schema} from '@loaders.gl/schema';
10
9
 
11
10
  import {fgbToBinaryGeometry} from './binary-geometries';
@@ -20,22 +19,15 @@ const deserializeGeoJson = geojson.deserialize;
20
19
  const deserializeGeneric = generic.deserialize;
21
20
  // const parsePropertiesBinary = FlatgeobufFeature.parseProperties;
22
21
 
23
- // TODO: reproject binary features
24
- function binaryFromFeature(feature: fgb.Feature, header: fgb.HeaderMeta) {
25
- const geometry = feature.geometry();
26
-
27
- // FlatGeobuf files can only hold a single geometry type per file, otherwise
28
- // GeometryType is GeometryCollection
29
- // I believe geometry.type() is null (0) except when the geometry type isn't
30
- // known in the header?
31
- const geometryType = header.geometryType || geometry?.type();
32
- const parsedGeometry = fgbToBinaryGeometry(geometry, geometryType!);
33
- // @ts-expect-error this looks wrong
34
- parsedGeometry.properties = parsePropertiesBinary(feature, header.columns);
35
-
36
- // TODO: wrap binary data either in points, lines, or polygons key
37
- return parsedGeometry;
38
- }
22
+ export type ParseFlatGeobufOptions = {
23
+ shape?: 'geojson-table' | 'columnar-table' | 'binary';
24
+ /** If supplied, only loads features within the bounding box */
25
+ boundingBox?: [[number, number], [number, number]];
26
+ /** Desired output CRS */
27
+ crs?: string;
28
+ /** Should geometries be reprojected to target CRS */
29
+ reproject?: boolean;
30
+ };
39
31
 
40
32
  /*
41
33
  * Parse FlatGeobuf arrayBuffer and return GeoJSON.
@@ -43,11 +35,8 @@ function binaryFromFeature(feature: fgb.Feature, header: fgb.HeaderMeta) {
43
35
  * @param arrayBuffer A FlatGeobuf arrayBuffer
44
36
  * @return A GeoJSON geometry object
45
37
  */
46
- export function parseFlatGeobuf(
47
- arrayBuffer: ArrayBuffer,
48
- options?: FlatGeobufLoaderOptions
49
- ): Table {
50
- const shape = options?.flatgeobuf?.shape;
38
+ export function parseFlatGeobuf(arrayBuffer: ArrayBuffer, options: ParseFlatGeobufOptions): Table {
39
+ const shape = options.shape;
51
40
 
52
41
  switch (shape) {
53
42
  case 'geojson-table': {
@@ -68,7 +57,7 @@ export function parseFlatGeobuf(
68
57
  }
69
58
  }
70
59
 
71
- function parseFlatGeobufToBinary(arrayBuffer: ArrayBuffer, options: FlatGeobufLoaderOptions = {}) {
60
+ function parseFlatGeobufToBinary(arrayBuffer: ArrayBuffer, options: ParseFlatGeobufOptions = {}) {
72
61
  // TODO: reproject binary features
73
62
  // const {reproject = false, _targetCrs = 'WGS84'} = (options && options.gis) || {};
74
63
 
@@ -79,32 +68,34 @@ function parseFlatGeobufToBinary(arrayBuffer: ArrayBuffer, options: FlatGeobufLo
79
68
 
80
69
  function parseFlatGeobufToGeoJSONTable(
81
70
  arrayBuffer: ArrayBuffer,
82
- options: FlatGeobufLoaderOptions = {}
71
+ options: ParseFlatGeobufOptions
83
72
  ): GeoJSONTable {
84
73
  if (arrayBuffer.byteLength === 0) {
85
74
  return {shape: 'geojson-table', type: 'FeatureCollection', features: []};
86
75
  }
87
76
 
88
- const {reproject = false, _targetCrs = 'WGS84'} = (options && options.gis) || {};
77
+ const {reproject = false, crs = 'WGS84'} = options;
89
78
 
90
79
  const arr = new Uint8Array(arrayBuffer);
91
80
 
92
- let fgbHeader;
81
+ let fgbHeader: fgb.HeaderMeta | undefined;
93
82
  let schema: Schema | undefined;
94
83
 
84
+ const rect = options.boundingBox && convertBoundingBox(options.boundingBox);
85
+
95
86
  // @ts-expect-error this looks wrong
96
- let {features} = deserializeGeoJson(arr, undefined, (headerMeta) => {
87
+ let {features} = deserializeGeoJson(arr, rect, (headerMeta) => {
97
88
  fgbHeader = headerMeta;
98
89
  schema = getSchemaFromFGBHeader(fgbHeader);
99
90
  });
100
91
 
101
- const crs = fgbHeader && fgbHeader.crs;
92
+ const fromCRS = fgbHeader?.crs?.wkt;
102
93
  let projection;
103
- if (reproject && crs) {
94
+ if (reproject && fromCRS) {
104
95
  // Constructing the projection may fail for some invalid WKT strings
105
96
  try {
106
- projection = new Proj4Projection({from: crs.wkt, to: _targetCrs});
107
- } catch (e) {
97
+ projection = new Proj4Projection({from: fromCRS, to: crs});
98
+ } catch (error) {
108
99
  // no op
109
100
  }
110
101
  }
@@ -123,8 +114,8 @@ function parseFlatGeobufToGeoJSONTable(
123
114
  * @return A GeoJSON geometry object iterator
124
115
  */
125
116
  // eslint-disable-next-line complexity
126
- export function parseFlatGeobufInBatches(stream, options: FlatGeobufLoaderOptions) {
127
- const shape = options.flatgeobuf?.shape;
117
+ export function parseFlatGeobufInBatches(stream, options: ParseFlatGeobufOptions) {
118
+ const shape = options.shape;
128
119
  switch (shape) {
129
120
  case 'binary':
130
121
  return parseFlatGeobufInBatchesToBinary(stream, options);
@@ -135,12 +126,14 @@ export function parseFlatGeobufInBatches(stream, options: FlatGeobufLoaderOption
135
126
  }
136
127
  }
137
128
 
138
- function parseFlatGeobufInBatchesToBinary(stream, options: FlatGeobufLoaderOptions) {
129
+ function parseFlatGeobufInBatchesToBinary(stream, options: ParseFlatGeobufOptions) {
139
130
  // TODO: reproject binary streaming features
140
131
  // const {reproject = false, _targetCrs = 'WGS84'} = (options && options.gis) || {};
141
132
 
133
+ const rect = options.boundingBox && convertBoundingBox(options.boundingBox);
134
+
142
135
  // @ts-expect-error
143
- const iterator = deserializeGeneric(stream, binaryFromFeature);
136
+ const iterator = deserializeGeneric(stream, binaryFromFeature, rect);
144
137
  return iterator;
145
138
  }
146
139
 
@@ -150,8 +143,8 @@ function parseFlatGeobufInBatchesToBinary(stream, options: FlatGeobufLoaderOptio
150
143
  * @param options
151
144
  */
152
145
  // eslint-disable-next-line complexity
153
- async function* parseFlatGeobufInBatchesToGeoJSON(stream, options: FlatGeobufLoaderOptions) {
154
- const {reproject = false, _targetCrs = 'WGS84'} = (options && options.gis) || {};
146
+ async function* parseFlatGeobufInBatchesToGeoJSON(stream, options: ParseFlatGeobufOptions) {
147
+ const {reproject = false, crs = 'WGS84'} = options || {};
155
148
 
156
149
  let fgbHeader;
157
150
  // let schema: Schema | undefined;
@@ -165,9 +158,9 @@ async function* parseFlatGeobufInBatchesToGeoJSON(stream, options: FlatGeobufLoa
165
158
  // @ts-expect-error this looks wrong
166
159
  for await (const feature of iterator) {
167
160
  if (firstRecord) {
168
- const crs = fgbHeader && fgbHeader.crs;
169
- if (reproject && crs) {
170
- projection = new Proj4Projection({from: crs.wkt, to: _targetCrs});
161
+ const fromCRS = fgbHeader?.crs?.wkt;
162
+ if (reproject && fromCRS) {
163
+ projection = new Proj4Projection({from: fromCRS, to: crs});
171
164
  }
172
165
 
173
166
  firstRecord = false;
@@ -181,3 +174,31 @@ async function* parseFlatGeobufInBatchesToGeoJSON(stream, options: FlatGeobufLoa
181
174
  }
182
175
  }
183
176
  }
177
+
178
+ // HELPERS
179
+
180
+ function convertBoundingBox(boundingBox: [[number, number], [number, number]]): fgb.Rect {
181
+ return {
182
+ minX: boundingBox[0][0],
183
+ minY: boundingBox[0][1],
184
+ maxX: boundingBox[1][0],
185
+ maxY: boundingBox[1][1]
186
+ };
187
+ }
188
+
189
+ // TODO: reproject binary features
190
+ function binaryFromFeature(feature: fgb.Feature, header: fgb.HeaderMeta) {
191
+ const geometry = feature.geometry();
192
+
193
+ // FlatGeobuf files can only hold a single geometry type per file, otherwise
194
+ // GeometryType is GeometryCollection
195
+ // I believe geometry.type() is null (0) except when the geometry type isn't
196
+ // known in the header?
197
+ const geometryType = header.geometryType || geometry?.type();
198
+ const parsedGeometry = fgbToBinaryGeometry(geometry, geometryType!);
199
+ // @ts-expect-error this looks wrong
200
+ parsedGeometry.properties = parsePropertiesBinary(feature, header.columns);
201
+
202
+ // TODO: wrap binary data either in points, lines, or polygons key
203
+ return parsedGeometry;
204
+ }