public static byte[] ToFlatGeobuf(FeatureCollection fc, GeometryType?geometryType = null, byte dimensions = 2, IList <ColumnMeta> columns = null) { ulong count = (ulong)fc.Features.LongCount(); if (count == 0) { return(new byte[0]); } var index = new PackedHilbertRTree(count); foreach (var f in fc.Features) { var b = f.Geometry.EnvelopeInternal; index.Add(b.MinX, b.MinY, b.MaxX, b.MaxY); } index.Finish(); var featureFirst = fc.Features.First(); if (geometryType == null) { geometryType = GeometryConversions.ToGeometryType(featureFirst.Geometry); } if (columns == null && featureFirst.Attributes != null) { columns = featureFirst.Attributes.GetNames() .Select(n => new ColumnMeta() { Name = n, Type = ToColumnType(featureFirst.Attributes.GetType(n)) }) .ToList(); } using (var memoryStream = new MemoryStream()) { using (var featuresStream = new MemoryStream()) using (var offsetsStream = new MemoryStream()) using (var offetsWriter = new BinaryWriter(offsetsStream)) { ulong offset = 0; for (ulong i = 0; i < count; i++) { var feature = fc.Features[(int)index.Indices[i]]; var buffer = FeatureConversions.ToByteBuffer(feature, geometryType.Value, dimensions, columns); featuresStream.Write(buffer, 0, buffer.Length); offetsWriter.Write(offset); offset += (ulong)buffer.Length; } var header = BuildHeader(count, geometryType.Value, dimensions, columns, index); memoryStream.Write(header, 0, header.Length); var indexBytes = index.ToBytes(); memoryStream.Write(indexBytes, 0, indexBytes.Length); offsetsStream.WriteTo(memoryStream); featuresStream.WriteTo(memoryStream); } return(memoryStream.ToArray()); } }
private static IList <LayerMeta> IntrospectLayers(FeatureCollection fc) { var featureFirst = fc.Features.First(); IList <ColumnMeta> columns = null; if (featureFirst.Attributes != null && featureFirst.Attributes.Count > 0) { columns = featureFirst.Attributes.GetNames() .Select(n => new ColumnMeta() { Name = n, Type = ToColumnType(featureFirst.Attributes.GetType(n)) }) .ToList(); } var geometryTypes = fc.Features .Select(f => GeometryConversions.ToGeometryType(f.Geometry)) .Distinct(); IList <LayerMeta> layers = geometryTypes .Select(geometryType => new LayerMeta() { GeometryType = geometryType, Columns = columns }) .ToList(); return(layers); }
public static IFeature FromByteBuffer(ByteBuffer bb, GeometryType geometryType, byte dimensions, IList <ColumnMeta> columns = null) { var feature = Feature.GetRootAsFeature(bb); IAttributesTable attributesTable = null; var propertiesArray = feature.GetPropertiesArray(); if (propertiesArray != null && propertiesArray.Length > 0) { var memoryStream = new MemoryStream(propertiesArray); var reader = new BinaryReader(memoryStream); attributesTable = new AttributesTable(); while (memoryStream.Position < memoryStream.Length) { ushort i = reader.ReadUInt16(); var column = columns[i]; var type = column.Type; var name = column.Name; switch (type) { case ColumnType.Bool: attributesTable.AddAttribute(name, reader.ReadBoolean()); break; case ColumnType.Int: attributesTable.AddAttribute(name, reader.ReadInt32()); break; case ColumnType.Long: attributesTable.AddAttribute(name, reader.ReadInt64()); break; case ColumnType.Double: attributesTable.AddAttribute(name, reader.ReadDouble()); break; case ColumnType.String: int len = reader.ReadInt32(); var str = Encoding.UTF8.GetString(memoryStream.ToArray(), (int)memoryStream.Position, len); memoryStream.Position += len; attributesTable.AddAttribute(name, str); break; default: throw new ApplicationException("Unknown type"); } } } IGeometry geometry = null; if (feature.Geometry.HasValue) { geometry = GeometryConversions.FromFlatbuf(feature.Geometry.Value, geometryType); } var f = new NetTopologySuite.Features.Feature(geometry, attributesTable); return(f); }
public static void Serialize(Stream output, IEnumerable <IFeature> features, GeometryType geometryType, byte dimensions = 2, IList <ColumnMeta> columns = null) { output.Write(Constants.MagicBytes); var header = BuildHeader(0, geometryType, columns, null); output.Write(header); foreach (var feature in features) { var featureGeometryType = geometryType == GeometryType.Unknown ? GeometryConversions.ToGeometryType(feature.Geometry) : geometryType; var buffer = FeatureConversions.ToByteBuffer(feature, featureGeometryType, dimensions, columns); output.Write(buffer); } }
public static byte[] ToByteBuffer(IFeature feature, IList <LayerMeta> layers) { // TODO: size might not be enough, need to be adaptive var builder = new FlatBufferBuilder(1024); // TODO: improve layer introspection var layer = layers.First(l => l.GeometryType == GeometryConversions.ToGeometryType(feature.Geometry)); var layerIndex = (uint)layers.IndexOf(layer); var columns = layer.Columns; var geometryOffset = GeometryConversions.BuildGeometry(builder, feature.Geometry); VectorOffset?valuesOffset = null; if (feature.Attributes != null && feature.Attributes.Count > 0 && columns != null) { var valueOffsets = new List <Offset <Value> >(); foreach (var column in columns) { if (feature.Attributes.Exists(column.Name)) { ushort columnIndex = (ushort)columns.IndexOf(column); var value = feature.Attributes[column.Name]; switch (value) { case bool v: valueOffsets.Add(Value.CreateValue(builder, columnIndex, bool_value: v)); break; case int v: valueOffsets.Add(Value.CreateValue(builder, columnIndex, int_value: v)); break; case long v: valueOffsets.Add(Value.CreateValue(builder, columnIndex, long_value: v)); break; case double v: valueOffsets.Add(Value.CreateValue(builder, columnIndex, double_value: v)); break; case string v: valueOffsets.Add(Value.CreateValue(builder, columnIndex, string_valueOffset: builder.CreateString(v))); break; case null: break; default: throw new ApplicationException("Unknown type"); } } } valuesOffset = Feature.CreateValuesVector(builder, valueOffsets.ToArray()); } Feature.StartFeature(builder); Feature.AddGeometry(builder, geometryOffset); Feature.AddLayer(builder, layerIndex); if (valuesOffset.HasValue) { Feature.AddValues(builder, valuesOffset.Value); } var offset = Feature.EndFeature(builder); builder.FinishSizePrefixed(offset.Value); var bytes = builder.DataBuffer.ToSizedArray(); return(bytes); }
public static IFeature FromByteBuffer(ByteBuffer bb, Header header) { // TODO: introspect which layer var columnsLayer = header.Layers(0).Value; IList <Column> columns = null; if (columnsLayer.ColumnsLength > 0) { columns = new List <Column>(); for (int i = 0; i < columnsLayer.ColumnsLength; i++) { var column = columnsLayer.Columns(i).Value; columns.Add(column); } } var feature = Feature.GetRootAsFeature(bb); IAttributesTable attributesTable = null; if (feature.ValuesLength > 0) { attributesTable = new AttributesTable(); } var layer = header.Layers((int)feature.Layer).Value; for (int i = 0; i < feature.ValuesLength; i++) { var value = feature.Values(i).Value; var column = columns[value.ColumnIndex]; switch (column.Type) { case ColumnType.Bool: attributesTable.AddAttribute(column.Name, value.BoolValue); break; case ColumnType.Int: attributesTable.AddAttribute(column.Name, value.IntValue); break; case ColumnType.Long: attributesTable.AddAttribute(column.Name, value.LongValue); break; case ColumnType.Double: attributesTable.AddAttribute(column.Name, value.DoubleValue); break; case ColumnType.String: attributesTable.AddAttribute(column.Name, value.StringValue); break; default: throw new ApplicationException("Unknown type"); } } var geometry = GeometryConversions.FromFlatbuf(feature.Geometry.Value, layer.GeometryType, layer.Dimensions); var f = new NetTopologySuite.Features.Feature(geometry, attributesTable); return(f); }
public static ByteBuffer ToByteBuffer(IFeature feature, ref Header header) { var builder = new FlatBufferBuilder(1024); GeometryType geometryType; if (header.GeometryType != GeometryType.Unknown) { geometryType = header.GeometryType; } else { geometryType = GeometryConversions.ToGeometryType(feature.Geometry); } var go = GeometryConversions.BuildGeometry(builder, feature.Geometry, geometryType, ref header); var memoryStream = new MemoryStream(); if (feature.Attributes != null && feature.Attributes.Count > 0 && header.ColumnsLength > 0) { var writer = new BinaryWriter(memoryStream, Encoding.UTF8); for (ushort i = 0; i < header.ColumnsLength; i++) { var column = header.Columns(i).Value; var type = column.Type; var name = column.Name; if (!feature.Attributes.Exists(name)) { continue; } var value = feature.Attributes[name]; if (value is null) { continue; } writer.Write(i); switch (type) { case ColumnType.Bool: writer.Write((bool)value); break; case ColumnType.Int: writer.Write((int)value); break; case ColumnType.Long: writer.Write((long)value); break; case ColumnType.Double: writer.Write((double)value); break; case ColumnType.String: var bytes = Encoding.UTF8.GetBytes((string)value); writer.Write(bytes.Length); writer.Write(bytes); break; default: throw new ApplicationException("Unknown type " + value.GetType().FullName); } } } var propertiesOffset = default(VectorOffset); if (memoryStream.Position > 0) { propertiesOffset = Feature.CreatePropertiesVectorBlock(builder, memoryStream.ToArray()); } Offset <Geometry> geometryOffset; if (go.gos != null && go.gos.Length > 0) { var partOffsets = new Offset <Geometry> [go.gos.Length]; for (int i = 0; i < go.gos.Length; i++) { var goPart = go.gos[i]; var partOffset = Geometry.CreateGeometry(builder, goPart.endsOffset, goPart.xyOffset, goPart.zOffset, goPart.mOffset, default, default, go.Type, default);
public static byte[] ToByteBuffer(IFeature feature, GeometryType geometryType, byte dimensions, IList <ColumnMeta> columns) { var builder = new FlatBufferBuilder(4096); var go = GeometryConversions.BuildGeometry(builder, feature.Geometry, geometryType, dimensions); var memoryStream = new MemoryStream(); if (feature.Attributes != null && feature.Attributes.Count > 0 && columns != null) { var writer = new BinaryWriter(memoryStream, Encoding.UTF8); for (ushort i = 0; i < columns.Count(); i++) { var column = columns[i]; var type = column.Type; var name = column.Name; if (!feature.Attributes.Exists(name)) { continue; } var value = feature.Attributes[name]; if (value is null) { continue; } writer.Write(i); switch (type) { case ColumnType.Bool: writer.Write((bool)value); break; case ColumnType.Int: writer.Write((int)value); break; case ColumnType.Long: writer.Write((long)value); break; case ColumnType.Double: writer.Write((double)value); break; case ColumnType.String: var bytes = Encoding.UTF8.GetBytes((string)value); writer.Write(bytes.Length); writer.Write(bytes); break; default: throw new ApplicationException("Unknown type " + value.GetType().FullName); } } } var propertiesOffset = default(VectorOffset); if (memoryStream.Position > 0) { propertiesOffset = Feature.CreatePropertiesVector(builder, memoryStream.ToArray()); } var geometryOffset = default(Offset <Geometry>); if (go.gos != null && go.gos.Length > 0) { var partOffsets = new Offset <Geometry> [go.gos.Length]; for (int i = 0; i < go.gos.Length; i++) { var goPart = go.gos[i]; var partOffset = Geometry.CreateGeometry(builder, goPart.endsOffset, goPart.coordsOffset, default(VectorOffset), default(VectorOffset), default(VectorOffset), default(VectorOffset), go.type, default(VectorOffset)); partOffsets[i] = partOffset; } var partsOffset = Geometry.CreatePartsVector(builder, partOffsets); geometryOffset = Geometry.CreateGeometry(builder, default(VectorOffset), default(VectorOffset), default(VectorOffset), default(VectorOffset), default(VectorOffset), default(VectorOffset), go.type, partsOffset); } else { geometryOffset = Geometry.CreateGeometry(builder, go.endsOffset, go.coordsOffset, default(VectorOffset), default(VectorOffset), default(VectorOffset), default(VectorOffset), go.type, default(VectorOffset)); } Feature.StartFeature(builder); Feature.AddGeometry(builder, geometryOffset); Feature.AddProperties(builder, propertiesOffset); var featureOffset = Feature.EndFeature(builder); builder.FinishSizePrefixed(featureOffset.Value); return(builder.DataBuffer.ToSizedArray()); }