Skip to content

FlatGeobuf

TANG ZhiXiong edited this page Nov 25, 2023 · 4 revisions

Try it.

$ ogr2ogr -f FlatGeobuf output.fgb data/suzhoubeizhan.json
Warning 1: The output driver does not natively support StringList type for field highlight_group. Misconversion can happen. -mapFieldType can be used to control field type conversion.
Warning 1: The output driver does not natively support StringList type for field nexts. Misconversion can happen. -mapFieldType can be used to control field type conversion.
Warning 1: The output driver does not natively support StringList type for field prevs. Misconversion can happen. -mapFieldType can be used to control field type conversion.
ERROR 1: ICreateFeature: Missing implementation for OGRFieldType 5
ERROR 1: Unable to write feature 0 from layer suzhoubeizhan.
ERROR 1: Terminating translation prematurely after failed
translation of layer suzhoubeizhan (use -skipfailures to skip errors)
ERROR 1: toColumnType: Unknown OGRFieldType 5
ERROR 1: toColumnType: Unknown OGRFieldType 5
ERROR 1: toColumnType: Unknown OGRFieldType 5

No features wrote out?!

import fiona

with fiona.open("data/suzhoubeizhan.json") as src:
    profile = src.profile
    profile["driver"] = "FlatGeobuf"
    with fiona.open("example.gfb", "w", **profile) as dst:
        for f in src:
            dst.write(f)
Traceback (most recent call last):
  File "/home/tzx/git/geobuf-cpp/test.py", line 8, in <module>
    dst.write(f)
  File "/home/tzx/miniconda3/envs/py39/lib/python3.9/site-packages/fiona/collection.py", line 568, in write
    self.writerecords([record])
  File "/home/tzx/miniconda3/envs/py39/lib/python3.9/site-packages/fiona/collection.py", line 558, in writerecords
    self.session.writerecs(records, self)
  File "fiona/ogrext.pyx", line 1409, in fiona.ogrext.WritingSession.writerecs
  File "fiona/ogrext.pyx", line 514, in fiona.ogrext.OGRFeatureBuilder.build
ValueError: Invalid field type <class 'list'>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "fiona/ogrext.pyx", line 639, in fiona.ogrext.Session.stop
  File "fiona/_err.pyx", line 198, in fiona._err.GDALErrCtxManager.__exit__
fiona._err.CPLE_AppDefinedError: b'toColumnType: Unknown OGRFieldType 5'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/tzx/git/geobuf-cpp/test.py", line 8, in <module>
    dst.write(f)
  File "/home/tzx/miniconda3/envs/py39/lib/python3.9/site-packages/fiona/collection.py", line 700, in __exit__
    self.close()
  File "/home/tzx/miniconda3/envs/py39/lib/python3.9/site-packages/fiona/collection.py", line 679, in close
    self.session.stop()
  File "fiona/ogrext.pyx", line 635, in fiona.ogrext.Session.stop
  File "fiona/ogrext.pyx", line 642, in fiona.ogrext.Session.stop
fiona.errors.DriverError: b'toColumnType: Unknown OGRFieldType 5'

src/ts/generic/feature.ts

export function parseProperties(
    feature: Feature,
    columns?: ColumnMeta[] | null,
): Record<string, unknown> {
    const properties: Record<string, unknown> = {};
    if (!columns || columns.length === 0) return properties;
    const array = feature.propertiesArray();
    if (!array) return properties;
    const view = new DataView(array.buffer, array.byteOffset);
    const length = feature.propertiesLength();
    let offset = 0;
    while (offset < length) {
        const i = view.getUint16(offset, true);
        offset += 2;
        const column = columns[i];
        const name = column.name;
        switch (column.type) {
            case ColumnType.Bool: {
                properties[name] = !!view.getUint8(offset);
                offset += 1;
                break;
            }
            case ColumnType.Byte: {
                properties[name] = view.getInt8(offset);
                offset += 1;
                break;
            }
            case ColumnType.UByte: {
                properties[name] = view.getUint8(offset);
                offset += 1;
                break;
            }
            case ColumnType.Short: {
                properties[name] = view.getInt16(offset, true);
                offset += 2;
                break;
            }
            case ColumnType.UShort: {
                properties[name] = view.getUint16(offset, true);
                offset += 2;
                break;
            }
            case ColumnType.Int: {
                properties[name] = view.getInt32(offset, true);
                offset += 4;
                break;
            }
            case ColumnType.UInt: {
                properties[name] = view.getUint32(offset, true);
                offset += 4;
                break;
            }
            case ColumnType.Long: {
                properties[name] = Number(view.getBigInt64(offset, true));
                offset += 8;
                break;
            }
            case ColumnType.ULong: {
                properties[name] = Number(view.getBigUint64(offset, true));
                offset += 8;
                break;
            }
            case ColumnType.Float: {
                properties[name] = view.getFloat32(offset, true);
                offset += 4;
                break;
            }
            case ColumnType.Double: {
                properties[name] = view.getFloat64(offset, true);
                offset += 8;
                break;
            }
            case ColumnType.DateTime:
            case ColumnType.String: {
                const length = view.getUint32(offset, true);
                offset += 4;
                properties[name] = textDecoder.decode(
                    array.subarray(offset, offset + length),
                );
                offset += length;
                break;
            }
            case ColumnType.Json: {
                const length = view.getUint32(offset, true);
                offset += 4;
                const str = textDecoder.decode(
                    array.subarray(offset, offset + length),
                );
                properties[name] = JSON.parse(str);
                offset += length;
                break;
            }
            default:
                throw new Error('Unknown type ' + column.type);
        }
    }
    return properties;
}

TODO, porting this to geobuf_index: https://flatgeobuf.org/examples/leaflet/large.html

Clone this wiki locally