FlatGeobuf format input/output

main
bjornharrtell 2021-09-17 21:27:44 +02:00
parent 3083021ce2
commit 3ae2c58440
48 changed files with 15013 additions and 5 deletions

1
.github/codecov.yml vendored
View File

@ -9,3 +9,4 @@ coverage:
comment: false
ignore:
- "deps/wagyu/include/**/*" # Ignore wagyu library files
- "deps/flatgeobuf/**/*" # Ignore FlatGeobuf library files

1
.gitignore vendored
View File

@ -196,3 +196,4 @@ postgis/uninstall_sfcgal.sql
deps/Makefile
deps/wagyu/Makefile
deps/ryu/Makefile
deps/flatgeobuf/Makefile

View File

@ -1548,6 +1548,73 @@ DEPS_MAKEFILE_LIST="$DEPS_MAKEFILE_LIST
deps/ryu/Makefile"
dnl ===========================================================================
dnl FlatGeobuf
dnl ===========================================================================
DEPS_SUBDIR="deps"
AC_SUBST([DEPS_SUBDIR])
FLATGEOBUF_LIB=libflatgeobuf.la
AC_SUBST([FLATGEOBUF_LIB])
dnl ============================================================
dnl We force to use the same compiler as Postgresql
dnl ============================================================
CXX_SAVE="$CXX"
CC_SAVE="$CC"
CFLAGS_SAVE="$CFLAGS"
CXXFLAGS_SAVE="$CXXFLAGS"
CPPFLAGS_SAVE="$CPPFLAGS"
LDFLAGS_SAVE="$LDFLAGS"
LIBS_SAVE="$LIBS"
FLATGEOBUF_CXX=`"$PG_CONFIG" --cc`
CPPFLAGS="-x c++"
CFLAGS=""
LDFLAGS=""
LIBS=""
CXX="$FLATGEOBUF_CXX"
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX(11, noext, mandatory)
FLATGEOBUF_CXX="$CXX -x c++"
dnl ============================================================
dnl Check if we can declare the c++ stdlib
dnl ============================================================
CC="$FLATGEOBUF_CXX"
AC_CHECK_LIB(c++, main, [HAVE_CPP=yes], [HAVE_CPP=no])
AC_CHECK_LIB(stdc++, main, [HAVE_STDCPP=yes], [HAVE_STDCPP=no])
if test "x$HAVE_CPP" = "xyes"; then
WFLATGEOBUF_LDFLAGS="-lc++"
elif test "x$HAVE_STDCPP" = "xyes"; then
FLATGEOBUF_LDFLAGS="-lstdc++"
else
AC_MSG_WARN("Could not find a C++ standard library")
FLATGEOBUF_LDFLAGS=""
fi
CXX="$CXX_SAVE"
CC="$CC_SAVE"
CFLAGS="$CFLAGS_SAVE"
CXXFLAGS="$CXXFLAGS_SAVE"
CPPFLAGS="$CPPFLAGS_SAVE"
LDFLAGS="$LDFLAGS_SAVE"
LIBS="$LIBS_SAVE"
HAVE_FLATGEOBUF=yes
AC_DEFINE([HAVE_FLATGEOBUF], [1], [Define to 1 if FlatGeobuf is being built])
AC_SUBST([HAVE_FLATGEOBUF])
AC_SUBST([FLATGEOBUF_CXX])
AC_SUBST([FLATGEOBUF_LDFLAGS])
DEPS_MAKEFILE_LIST="$DEPS_MAKEFILE_LIST
deps/flatgeobuf/Makefile"
dnl ===========================================================================
dnl See if we have the requirements for building the extensions, namely
dnl the xlstproc tool for generating the comments SQL file.
@ -1614,6 +1681,9 @@ AC_MSG_RESULT([ C compiler: ${CC} ${CFLAGS}])
if test "x$HAVE_WAGYU" = "xyes"; then
AC_MSG_RESULT([ C++ compiler (Wagyu): ${WAGYU_CXX} ${CXXFLAGS}])
fi
if test "x$HAVE_FLATGEOBUF" = "xyes"; then
AC_MSG_RESULT([ C++ compiler (FlatGeobuf): ${FLATGEOBUF_CXX} ${CXXFLAGS}])
fi
AC_MSG_RESULT([ CPPFLAGS: $CPPFLAGS])
AC_MSG_RESULT([ LDFLAGS: $LDFLAGS])
AC_MSG_RESULT([ SQL preprocessor: ${SQLPP}])

7
deps/Makefile.in vendored
View File

@ -31,7 +31,7 @@ top_builddir = @top_builddir@
libdir = @libdir@
LIBTOOL = @LIBTOOL@
all: @WAGYU_LIB@ @RYU_LIB@
all: @WAGYU_LIB@ @RYU_LIB@ @FLATGEOBUF_LIB@
@WAGYU_LIB@:
$(MAKE) -C wagyu $@
@ -39,13 +39,18 @@ all: @WAGYU_LIB@ @RYU_LIB@
@RYU_LIB@:
$(MAKE) -C ryu $@
@FLATGEOBUF_LIB@:
$(MAKE) -C flatgeobuf $@
clean:
$(MAKE) -C wagyu $@
$(MAKE) -C ryu $@
$(MAKE) -C flatgeobuf $@
distclean: clean
$(MAKE) -C wagyu $@
$(MAKE) -C ryu $@
$(MAKE) -C flatgeobuf $@
rm -f Makefile
.PHONY: install uninstall check check-unit check-regress

68
deps/flatgeobuf/Makefile.in vendored Normal file
View File

@ -0,0 +1,68 @@
#/**********************************************************************
# *
# * PostGIS - Spatial Types for PostgreSQL
# * http://postgis.net
# *
# * PostGIS is free software: you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation, either version 2 of the License, or
# * (at your option) any later version.
# *
# * PostGIS is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
# *
# **********************************************************************
# *
# * Copyright 2021 Björn Harrtell
# *
# **********************************************************************/
CXX = @FLATGEOBUF_CXX@
CXXFLAGS =-I../../liblwgeom -Iinclude @CPPFLAGS@ @CXXFLAGS@ @PICFLAGS@
LDFLAGS = @LDFLAGS@
top_builddir = @top_builddir@
libdir = @libdir@
LIBTOOL = @LIBTOOL@
FLATGEOBUF_OBJS = \
flatgeobuf_c.o geometrywriter.o geometryreader.o packedrtree.o
FLATGEOBUF_HEADERS = \
flatgeobuf_c.h \
geometrywriter.h \
geometryreader.h \
packedrtree.h \
include/flatbuffers/flatbuffers.h \
include/flatbuffers/base.h \
include/flatbuffers/stl_emulation.h
all: @FLATGEOBUF_LIB@
@FLATGEOBUF_LIB@: $(FLATGEOBUF_OBJS)
ar rs @FLATGEOBUF_LIB@ $(FLATGEOBUF_OBJS)
$(FLATGEOBUF_OBJS): %.o: %.cpp ../../liblwgeom/liblwgeom.h $(FLATGEOBUF_HEADERS)
$(CXX) $(CXXFLAGS) -c -o $@ $<
../../liblwgeom/liblwgeom.h:
$(MAKE) -C ../../liblwgeom liblwgeom.h
clean:
rm -f @FLATGEOBUF_LIB@ $(FLATGEOBUF_OBJS)
distclean: clean
rm -f Makefile
install:
uninstall:
check:
.PHONY: clean distclean install uninstall check

278
deps/flatgeobuf/feature_generated.h vendored Normal file
View File

@ -0,0 +1,278 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_FEATURE_FLATGEOBUF_H_
#define FLATBUFFERS_GENERATED_FEATURE_FLATGEOBUF_H_
#include "flatbuffers/flatbuffers.h"
#include "header_generated.h"
namespace FlatGeobuf {
struct Geometry;
struct GeometryBuilder;
struct Feature;
struct FeatureBuilder;
struct Geometry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef GeometryBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_ENDS = 4,
VT_XY = 6,
VT_Z = 8,
VT_M = 10,
VT_T = 12,
VT_TM = 14,
VT_TYPE = 16,
VT_PARTS = 18
};
const flatbuffers::Vector<uint32_t> *ends() const {
return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_ENDS);
}
const flatbuffers::Vector<double> *xy() const {
return GetPointer<const flatbuffers::Vector<double> *>(VT_XY);
}
const flatbuffers::Vector<double> *z() const {
return GetPointer<const flatbuffers::Vector<double> *>(VT_Z);
}
const flatbuffers::Vector<double> *m() const {
return GetPointer<const flatbuffers::Vector<double> *>(VT_M);
}
const flatbuffers::Vector<double> *t() const {
return GetPointer<const flatbuffers::Vector<double> *>(VT_T);
}
const flatbuffers::Vector<uint64_t> *tm() const {
return GetPointer<const flatbuffers::Vector<uint64_t> *>(VT_TM);
}
FlatGeobuf::GeometryType type() const {
return static_cast<FlatGeobuf::GeometryType>(GetField<uint8_t>(VT_TYPE, 0));
}
const flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Geometry>> *parts() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Geometry>> *>(VT_PARTS);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_ENDS) &&
verifier.VerifyVector(ends()) &&
VerifyOffset(verifier, VT_XY) &&
verifier.VerifyVector(xy()) &&
VerifyOffset(verifier, VT_Z) &&
verifier.VerifyVector(z()) &&
VerifyOffset(verifier, VT_M) &&
verifier.VerifyVector(m()) &&
VerifyOffset(verifier, VT_T) &&
verifier.VerifyVector(t()) &&
VerifyOffset(verifier, VT_TM) &&
verifier.VerifyVector(tm()) &&
VerifyField<uint8_t>(verifier, VT_TYPE) &&
VerifyOffset(verifier, VT_PARTS) &&
verifier.VerifyVector(parts()) &&
verifier.VerifyVectorOfTables(parts()) &&
verifier.EndTable();
}
};
struct GeometryBuilder {
typedef Geometry Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_ends(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> ends) {
fbb_.AddOffset(Geometry::VT_ENDS, ends);
}
void add_xy(flatbuffers::Offset<flatbuffers::Vector<double>> xy) {
fbb_.AddOffset(Geometry::VT_XY, xy);
}
void add_z(flatbuffers::Offset<flatbuffers::Vector<double>> z) {
fbb_.AddOffset(Geometry::VT_Z, z);
}
void add_m(flatbuffers::Offset<flatbuffers::Vector<double>> m) {
fbb_.AddOffset(Geometry::VT_M, m);
}
void add_t(flatbuffers::Offset<flatbuffers::Vector<double>> t) {
fbb_.AddOffset(Geometry::VT_T, t);
}
void add_tm(flatbuffers::Offset<flatbuffers::Vector<uint64_t>> tm) {
fbb_.AddOffset(Geometry::VT_TM, tm);
}
void add_type(FlatGeobuf::GeometryType type) {
fbb_.AddElement<uint8_t>(Geometry::VT_TYPE, static_cast<uint8_t>(type), 0);
}
void add_parts(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Geometry>>> parts) {
fbb_.AddOffset(Geometry::VT_PARTS, parts);
}
explicit GeometryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<Geometry> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Geometry>(end);
return o;
}
};
inline flatbuffers::Offset<Geometry> CreateGeometry(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> ends = 0,
flatbuffers::Offset<flatbuffers::Vector<double>> xy = 0,
flatbuffers::Offset<flatbuffers::Vector<double>> z = 0,
flatbuffers::Offset<flatbuffers::Vector<double>> m = 0,
flatbuffers::Offset<flatbuffers::Vector<double>> t = 0,
flatbuffers::Offset<flatbuffers::Vector<uint64_t>> tm = 0,
FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType::Unknown,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Geometry>>> parts = 0) {
GeometryBuilder builder_(_fbb);
builder_.add_parts(parts);
builder_.add_tm(tm);
builder_.add_t(t);
builder_.add_m(m);
builder_.add_z(z);
builder_.add_xy(xy);
builder_.add_ends(ends);
builder_.add_type(type);
return builder_.Finish();
}
inline flatbuffers::Offset<Geometry> CreateGeometryDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<uint32_t> *ends = nullptr,
const std::vector<double> *xy = nullptr,
const std::vector<double> *z = nullptr,
const std::vector<double> *m = nullptr,
const std::vector<double> *t = nullptr,
const std::vector<uint64_t> *tm = nullptr,
FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType::Unknown,
const std::vector<flatbuffers::Offset<FlatGeobuf::Geometry>> *parts = nullptr) {
auto ends__ = ends ? _fbb.CreateVector<uint32_t>(*ends) : 0;
auto xy__ = xy ? _fbb.CreateVector<double>(*xy) : 0;
auto z__ = z ? _fbb.CreateVector<double>(*z) : 0;
auto m__ = m ? _fbb.CreateVector<double>(*m) : 0;
auto t__ = t ? _fbb.CreateVector<double>(*t) : 0;
auto tm__ = tm ? _fbb.CreateVector<uint64_t>(*tm) : 0;
auto parts__ = parts ? _fbb.CreateVector<flatbuffers::Offset<FlatGeobuf::Geometry>>(*parts) : 0;
return FlatGeobuf::CreateGeometry(
_fbb,
ends__,
xy__,
z__,
m__,
t__,
tm__,
type,
parts__);
}
struct Feature FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef FeatureBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_GEOMETRY = 4,
VT_PROPERTIES = 6,
VT_COLUMNS = 8
};
const FlatGeobuf::Geometry *geometry() const {
return GetPointer<const FlatGeobuf::Geometry *>(VT_GEOMETRY);
}
const flatbuffers::Vector<uint8_t> *properties() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_PROPERTIES);
}
const flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Column>> *columns() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Column>> *>(VT_COLUMNS);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_GEOMETRY) &&
verifier.VerifyTable(geometry()) &&
VerifyOffset(verifier, VT_PROPERTIES) &&
verifier.VerifyVector(properties()) &&
VerifyOffset(verifier, VT_COLUMNS) &&
verifier.VerifyVector(columns()) &&
verifier.VerifyVectorOfTables(columns()) &&
verifier.EndTable();
}
};
struct FeatureBuilder {
typedef Feature Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_geometry(flatbuffers::Offset<FlatGeobuf::Geometry> geometry) {
fbb_.AddOffset(Feature::VT_GEOMETRY, geometry);
}
void add_properties(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> properties) {
fbb_.AddOffset(Feature::VT_PROPERTIES, properties);
}
void add_columns(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Column>>> columns) {
fbb_.AddOffset(Feature::VT_COLUMNS, columns);
}
explicit FeatureBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<Feature> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Feature>(end);
return o;
}
};
inline flatbuffers::Offset<Feature> CreateFeature(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<FlatGeobuf::Geometry> geometry = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> properties = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Column>>> columns = 0) {
FeatureBuilder builder_(_fbb);
builder_.add_columns(columns);
builder_.add_properties(properties);
builder_.add_geometry(geometry);
return builder_.Finish();
}
inline flatbuffers::Offset<Feature> CreateFeatureDirect(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<FlatGeobuf::Geometry> geometry = 0,
const std::vector<uint8_t> *properties = nullptr,
const std::vector<flatbuffers::Offset<FlatGeobuf::Column>> *columns = nullptr) {
auto properties__ = properties ? _fbb.CreateVector<uint8_t>(*properties) : 0;
auto columns__ = columns ? _fbb.CreateVector<flatbuffers::Offset<FlatGeobuf::Column>>(*columns) : 0;
return FlatGeobuf::CreateFeature(
_fbb,
geometry,
properties__,
columns__);
}
inline const FlatGeobuf::Feature *GetFeature(const void *buf) {
return flatbuffers::GetRoot<FlatGeobuf::Feature>(buf);
}
inline const FlatGeobuf::Feature *GetSizePrefixedFeature(const void *buf) {
return flatbuffers::GetSizePrefixedRoot<FlatGeobuf::Feature>(buf);
}
inline bool VerifyFeatureBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<FlatGeobuf::Feature>(nullptr);
}
inline bool VerifySizePrefixedFeatureBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifySizePrefixedBuffer<FlatGeobuf::Feature>(nullptr);
}
inline void FinishFeatureBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<FlatGeobuf::Feature> root) {
fbb.Finish(root);
}
inline void FinishSizePrefixedFeatureBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<FlatGeobuf::Feature> root) {
fbb.FinishSizePrefixed(root);
}
} // namespace FlatGeobuf
#endif // FLATBUFFERS_GENERATED_FEATURE_FLATGEOBUF_H_

306
deps/flatgeobuf/flatgeobuf_c.cpp vendored Normal file
View File

@ -0,0 +1,306 @@
/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PostGIS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
*
**********************************************************************
*
* Copyright 2021 Björn Harrtell
*
**********************************************************************/
#include "flatgeobuf_c.h"
#include "feature_generated.h"
#include "geometrywriter.h"
#include "geometryreader.h"
#include "packedrtree.h"
using namespace flatbuffers;
using namespace FlatGeobuf;
typedef flatgeobuf_ctx ctx;
uint8_t flatgeobuf_magicbytes[] = { 0x66, 0x67, 0x62, 0x03, 0x66, 0x67, 0x62, 0x00 };
uint8_t FLATGEOBUF_MAGICBYTES_SIZE = sizeof(flatgeobuf_magicbytes);
uint8_t FLATGEOBUF_MAGICBYTES_LEN = (sizeof(flatgeobuf_magicbytes) / sizeof((flatgeobuf_magicbytes)[0]));
struct FeatureItem : FlatGeobuf::Item {
uoffset_t size;
uint64_t offset;
};
int flatgeobuf_encode_header(ctx *ctx)
{
FlatBufferBuilder fbb;
// inspect first geometry
if (ctx->lwgeom != NULL) {
if (lwgeom_has_srid(ctx->lwgeom))
ctx->srid = ctx->lwgeom->srid;
ctx->has_z = lwgeom_has_z(ctx->lwgeom);
ctx->has_m = lwgeom_has_m(ctx->lwgeom);
ctx->geometry_type = (uint8_t) GeometryWriter::get_geometrytype(ctx->lwgeom);
} else {
LWDEBUG(2, "ctx->lwgeom is null");
ctx->geometry_type = 0;
}
LWDEBUGF(2, "ctx->geometry_type %d", ctx->geometry_type);
std::vector<flatbuffers::Offset<FlatGeobuf::Column>> columns;
std::vector<flatbuffers::Offset<FlatGeobuf::Column>> *pColumns = nullptr;
if (ctx->columns_size > 0) {
for (uint16_t i = 0; i < ctx->columns_size; i++) {
auto c = ctx->columns[i];
columns.push_back(CreateColumnDirect(fbb, c->name, (ColumnType) c->type));
}
}
if (columns.size() > 0)
pColumns = &columns;
flatbuffers::Offset<Crs> crs = 0;
if (ctx->srid > 0)
crs = CreateCrsDirect(fbb, nullptr, ctx->srid);
std::vector<double> *pEnvelope = nullptr;
if (ctx->has_extent) {
std::vector<double> envelope = { ctx->xmin, ctx->ymin, ctx->xmax, ctx->ymax };
pEnvelope = &envelope;
}
const auto header = CreateHeaderDirect(
fbb, ctx->name, pEnvelope, (GeometryType) ctx->geometry_type, ctx->has_z, ctx->has_m, ctx->has_t, ctx->has_tm, pColumns, ctx->features_count, ctx->index_node_size, crs);
fbb.FinishSizePrefixed(header);
const auto buffer = fbb.GetBufferPointer();
const auto size = fbb.GetSize();
LWDEBUGF(2, "header size %d (with size prefix)", size);
Verifier verifier(buffer, size - sizeof(uoffset_t));
if (VerifySizePrefixedHeaderBuffer(verifier)) {
lwerror("buffer did not pass verification");
return -1;
}
ctx->buf = (uint8_t *) lwrealloc(ctx->buf, ctx->offset + size);
LWDEBUGF(2, "copying to ctx->buf at offset %ld", ctx->offset);
memcpy(ctx->buf + ctx->offset, buffer, size);
ctx->offset += size;
return 0;
}
int flatgeobuf_encode_feature(ctx *ctx)
{
FlatBufferBuilder fbb;
Offset<Geometry> geometry = 0;
Offset<Vector<uint8_t>> properties = 0;
if (ctx->lwgeom != NULL) {
LWDEBUGG(3, ctx->lwgeom, "GeometryWriter input LWGEOM");
GeometryWriter writer(fbb, ctx->lwgeom, (GeometryType) ctx->geometry_type, ctx->has_z, ctx->has_m);
geometry = writer.write(0);
}
if (ctx->properties_len > 0)
properties = fbb.CreateVector<uint8_t>(ctx->properties, ctx->properties_len);
FeatureBuilder builder(fbb);
builder.add_geometry(geometry);
builder.add_properties(properties);
auto feature = builder.Finish();
fbb.FinishSizePrefixed(feature);
const auto buffer = fbb.GetBufferPointer();
const auto size = fbb.GetSize();
LWDEBUGF(3, "encode_feature size %ld", size);
Verifier verifier(buffer, size - sizeof(uoffset_t));
if (VerifySizePrefixedFeatureBuffer(verifier)) {
lwerror("buffer did not pass verification");
return -1;
}
LWDEBUGF(3, "reallocating ctx->buf to size %ld", ctx->offset + size);
ctx->buf = (uint8_t * ) lwrealloc(ctx->buf, ctx->offset + size);
LWDEBUGF(3, "copying feature to ctx->buf at offset %ld", ctx->offset);
memcpy(ctx->buf + ctx->offset, buffer, size);
if (ctx->create_index) {
auto item = (flatgeobuf_item *) lwalloc(sizeof(flatgeobuf_item));
auto gbox = lwgeom_get_bbox(ctx->lwgeom);
item->xmin = gbox->xmin;
item->xmax = gbox->xmax;
item->ymin = gbox->ymin;
item->ymax = gbox->ymax;
item->offset = ctx->offset;
item->size = size;
ctx->items[ctx->features_count] = item;
}
ctx->offset += size;
ctx->features_count++;
return 0;
}
void flatgeobuf_create_index(ctx *ctx)
{
// convert to structure expected by packedrtree
std::vector<std::shared_ptr<Item>> items;
for (uint64_t i = 0; i < ctx->features_count; i++) {
const auto item = std::make_shared<FeatureItem>();
item->nodeItem = {
ctx->items[i]->xmin, ctx->items[i]->ymin, ctx->items[i]->xmax, ctx->items[i]->ymax
};
item->offset = ctx->items[i]->offset;
item->size = ctx->items[i]->size;
items.push_back(item);
}
// sort items
hilbertSort(items);
// calc extent
auto extent = calcExtent(items);
ctx->has_extent = true;
ctx->xmin = extent.minX;
ctx->ymin = extent.minY;
ctx->xmax = extent.maxX;
ctx->ymax = extent.maxY;
// allocate new buffer and write magicbytes
auto oldbuf = ctx->buf;
auto oldoffset = ctx->offset;
ctx->buf = (uint8_t *) lwalloc(sizeof(signed int) + sizeof(flatgeobuf_magicbytes));
memcpy(ctx->buf + sizeof(signed int), flatgeobuf_magicbytes, sizeof(flatgeobuf_magicbytes));
ctx->offset = sizeof(signed int) + sizeof(flatgeobuf_magicbytes);
// write new header
flatgeobuf_encode_header(ctx);
// create and write index
const auto writeData = [&ctx] (const void *data, const size_t size) {
ctx->buf = (uint8_t *) lwrealloc(ctx->buf, ctx->offset + size);
memcpy(ctx->buf + ctx->offset, data, size);
};
PackedRTree tree(items, extent, ctx->index_node_size);
tree.streamWrite(writeData);
ctx->offset += tree.size();
// read items and write in sorted order
for (auto item : items) {
auto featureItem = std::static_pointer_cast<FeatureItem>(item);
ctx->buf = (uint8_t *) lwrealloc(ctx->buf, ctx->offset + featureItem->size);
LWDEBUGF(2, "copy from offset %ld", featureItem->offset);
memcpy(ctx->buf + ctx->offset, oldbuf + featureItem->offset, featureItem->size);
ctx->offset += featureItem->size;
}
lwfree(oldbuf);
}
int flatgeobuf_decode_feature(ctx *ctx)
{
LWDEBUGF(2, "reading size prefix at %ld", ctx->offset);
auto size = flatbuffers::GetPrefixedSize(ctx->buf + ctx->offset);
LWDEBUGF(2, "size is %ld (without size prefix)", size);
Verifier verifier(ctx->buf + ctx->offset, size);
if (VerifySizePrefixedFeatureBuffer(verifier)) {
lwerror("buffer did not pass verification");
return -1;
}
ctx->offset += sizeof(uoffset_t);
auto feature = GetFeature(ctx->buf + ctx->offset);
ctx->offset += size;
const auto geometry = feature->geometry();
if (geometry != nullptr) {
if (geometry->ends() != nullptr) {
LWDEBUGF(3, "ENDS: %d", geometry->ends()->size());
for (uint32_t i = 0; i < geometry->ends()->size(); i++) {
LWDEBUGF(3, "ENDS: %d", geometry->ends()->Get(i));
}
}
LWDEBUGF(3, "Constructing GeometryReader with geometry_type %d has_z %d haz_m %d", ctx->geometry_type, ctx->has_z, ctx->has_m);
GeometryReader reader(geometry, (GeometryType) ctx->geometry_type, ctx->has_z, ctx->has_m);
ctx->lwgeom = reader.read();
if (ctx->srid > 0)
lwgeom_set_srid(ctx->lwgeom, ctx->srid);
LWDEBUGG(3, ctx->lwgeom, "GeometryReader output LWGEOM");
} else {
ctx->lwgeom = NULL;
}
if (feature->properties() != nullptr && feature->properties()->size() != 0) {
ctx->properties = (uint8_t *) feature->properties()->data();
ctx->properties_len = feature->properties()->size();
} else {
ctx->properties_len = 0;
}
return 0;
}
int flatgeobuf_decode_header(ctx *ctx)
{
LWDEBUGF(2, "reading size prefix at %ld", ctx->offset);
auto size = flatbuffers::GetPrefixedSize(ctx->buf + ctx->offset);
LWDEBUGF(2, "size is %ld (without size prefix)", size);
Verifier verifier(ctx->buf + ctx->offset, size);
if (VerifySizePrefixedHeaderBuffer(verifier)) {
lwerror("buffer did not pass verification");
return -1;
}
ctx->offset += sizeof(uoffset_t);
LWDEBUGF(2, "reading header at %ld with size %ld", ctx->offset, size);
auto header = GetHeader(ctx->buf + ctx->offset);
ctx->offset += size;
ctx->geometry_type = (uint8_t) header->geometry_type();
ctx->features_count = header->features_count();
ctx->has_z = header->has_z();
ctx->has_m = header->has_m();
ctx->has_t = header->has_t();
ctx->has_tm = header->has_tm();
ctx->index_node_size = header->index_node_size();
auto crs = header->crs();
if (crs != nullptr)
ctx->srid = crs->code();
auto columns = header->columns();
if (columns != nullptr) {
auto size = columns->size();
ctx->columns = (flatgeobuf_column **) lwalloc(sizeof(flatgeobuf_column *) * size);
ctx->columns_size = size;
for (uint32_t i = 0; i < size; i++) {
auto column = columns->Get(i);
ctx->columns[i] = (flatgeobuf_column *) lwalloc(sizeof(flatgeobuf_column));
memset(ctx->columns[i], 0, sizeof(flatgeobuf_column));
ctx->columns[i]->name = column->name()->c_str();
ctx->columns[i]->type = (uint8_t) column->type();
}
}
LWDEBUGF(2, "ctx->geometry_type: %d", ctx->geometry_type);
LWDEBUGF(2, "ctx->columns_len: %d", ctx->columns_size);
if (ctx->index_node_size > 0 && ctx->features_count > 0) {
auto treeSize = PackedRTree::size(ctx->features_count, ctx->index_node_size);
LWDEBUGF(2, "Adding tree size %ld to offset", treeSize);
ctx->offset += treeSize;
}
return 0;
}

132
deps/flatgeobuf/flatgeobuf_c.h vendored Normal file
View File

@ -0,0 +1,132 @@
/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PostGIS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
*
**********************************************************************
*
* Copyright 2021 Björn Harrtell
*
**********************************************************************/
#ifndef FLATGEOBUF_C_H
#define FLATGEOBUF_C_H
#ifdef __cplusplus
extern "C" {
#endif
#include "liblwgeom.h"
#include "lwgeom_log.h"
extern uint8_t flatgeobuf_magicbytes[];
extern uint8_t FLATGEOBUF_MAGICBYTES_SIZE;
extern uint8_t FLATGEOBUF_MAGICBYTES_LEN;
// need c compatible variant of this enum
#define flatgeobuf_column_type_byte UINT8_C(0)
#define flatgeobuf_column_type_ubyte UINT8_C(1)
#define flatgeobuf_column_type_bool UINT8_C(2)
#define flatgeobuf_column_type_short UINT8_C(3)
#define flatgeobuf_column_type_ushort UINT8_C(4)
#define flatgeobuf_column_type_int UINT8_C(5)
#define flatgeobuf_column_type_uint UINT8_C(6)
#define flatgeobuf_column_type_long UINT8_C(7)
#define flatgeobuf_column_type_ulong UINT8_C(8)
#define flatgeobuf_column_type_float UINT8_C(9)
#define flatgeobuf_column_type_double UINT8_C(10)
#define flatgeobuf_column_type_string UINT8_C(11)
#define flatgeobuf_column_type_json UINT8_C(12)
#define flatgeobuf_column_type_datetime UINT8_C(13)
#define flatgeobuf_column_type_binary UINT8_C(14)
typedef struct flatgeobuf_column
{
const char *name;
uint8_t type;
const char *title;
const char *description;
uint32_t width;
uint32_t precision;
uint32_t scale;
bool nullable;
bool unique;
bool primary_key;
const char * metadata;
} flatgeobuf_column;
typedef struct flatgeobuf_item
{
double xmin;
double xmax;
double ymin;
double ymax;
uint32_t size;
uint64_t offset;
} flatgeobuf_item;
typedef struct flatgeobuf_ctx
{
// header contents
const char *name;
uint64_t features_count;
uint8_t geometry_type;
bool has_extent;
double xmin;
double xmax;
double ymin;
double ymax;
bool has_z;
bool has_m;
bool has_t;
bool has_tm;
uint16_t index_node_size;
int32_t srid;
flatgeobuf_column **columns;
uint16_t columns_size;
// encode/decode buffers
uint8_t *buf;
uint64_t offset;
uint64_t size;
LWGEOM *lwgeom;
uint8_t *properties;
uint32_t properties_len;
uint32_t properties_size;
// encode input
const char *geom_name;
uint32_t geom_index;
// encode spatial index bookkeeping
bool create_index;
flatgeobuf_item **items;
uint64_t items_len;
} flatgeobuf_ctx;
int flatgeobuf_encode_header(flatgeobuf_ctx *ctx);
int flatgeobuf_encode_feature(flatgeobuf_ctx *ctx);
void flatgeobuf_create_index(flatgeobuf_ctx *ctx);
int flatgeobuf_decode_header(flatgeobuf_ctx *ctx);
int flatgeobuf_decode_feature(flatgeobuf_ctx *ctx);
#ifdef __cplusplus
}
#endif
#endif /* LWGEOM_WAGYU_H */

205
deps/flatgeobuf/geometryreader.cpp vendored Normal file
View File

@ -0,0 +1,205 @@
/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PostGIS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
*
**********************************************************************
*
* Copyright 2021 Björn Harrtell
*
**********************************************************************/
#include "geometryreader.h"
using namespace flatbuffers;
using namespace FlatGeobuf;
LWPOINT *GeometryReader::readPoint()
{
POINTARRAY *pa;
POINT4D pt;
pa = ptarray_construct_empty(m_has_z, m_has_m, 1);
if (m_geometry->xy() == nullptr || m_geometry->xy()->size() == 0) {
return lwpoint_construct(0, NULL, pa);
}
const auto xy = m_geometry->xy()->data();
double x = xy[m_offset + 0];
double y = xy[m_offset + 1];
double z = 0;
double m = 0;
if (m_has_z)
z = m_geometry->z()->data()[m_offset];
if (m_has_m)
m = m_geometry->m()->data()[m_offset];
pt = (POINT4D) { x, y, z, m };
ptarray_append_point(pa, &pt, LW_TRUE);
return lwpoint_construct(0, NULL, pa);
}
POINTARRAY *GeometryReader::readPA()
{
POINTARRAY *pa;
POINT4D pt;
uint32_t npoints;
const double *xy = m_geometry->xy()->data();
const double *z = m_has_z ? m_geometry->z()->data() : nullptr;
const double *m = m_has_m ? m_geometry->m()->data() : nullptr;
pa = ptarray_construct_empty(m_has_z, m_has_m, m_length);
for (uint32_t i = m_offset; i < m_offset + m_length; i++) {
double xv = xy[i * 2 + 0];
double yv = xy[i * 2 + 1];
double zv = 0;
double mv = 0;
if (m_has_z)
zv = z[i];
if (m_has_m)
mv = m[i];
pt = (POINT4D) { xv, yv, zv, mv };
ptarray_append_point(pa, &pt, LW_TRUE);
}
return pa;
}
LWMPOINT *GeometryReader::readMultiPoint()
{
POINTARRAY *pa = readPA();
return lwmpoint_construct(0, pa);
}
LWLINE *GeometryReader::readLineString()
{
POINTARRAY *pa = readPA();
return lwline_construct(0, NULL, pa);
}
LWMLINE *GeometryReader::readMultiLineString()
{
auto ends = m_geometry->ends();
uint32_t ngeoms = 1;
if (ends != nullptr && ends->size() > 1)
ngeoms = ends->size();
auto *lwmline = lwmline_construct_empty(0, m_has_z, m_has_m);
if (ngeoms > 1) {
for (uint32_t i = 0; i < ngeoms; i++) {
const auto e = ends->Get(i);
m_length = e - m_offset;
POINTARRAY *pa = readPA();
lwmline_add_lwline(lwmline, lwline_construct(0, NULL, pa));
m_offset = e;
}
} else {
POINTARRAY *pa = readPA();
lwmline_add_lwline(lwmline, lwline_construct(0, NULL, pa));
}
return lwmline;
}
LWPOLY *GeometryReader::readPolygon()
{
const auto ends = m_geometry->ends();
uint32_t nrings = 1;
if (ends != nullptr && ends->size() > 1)
nrings = ends->size();
auto **ppa = (POINTARRAY **) lwalloc(sizeof(POINTARRAY *) * nrings);
if (nrings > 1) {
for (uint32_t i = 0; i < nrings; i++) {
const auto e = ends->Get(i);
m_length = e - m_offset;
ppa[i] = readPA();
m_offset = e;
}
} else {
ppa[0] = readPA();
}
return lwpoly_construct(0, NULL, nrings, ppa);
}
LWMPOLY *GeometryReader::readMultiPolygon()
{
auto parts = m_geometry->parts();
auto *mp = lwmpoly_construct_empty(0, m_has_z, m_has_m);
for (uoffset_t i = 0; i < parts->size(); i++) {
GeometryReader reader { parts->Get(i), GeometryType::Polygon, m_has_z, m_has_m };
const auto p = (LWPOLY *) reader.read();
lwmpoly_add_lwpoly(mp, p);
}
return mp;
}
LWCOLLECTION *GeometryReader::readGeometryCollection()
{
auto parts = m_geometry->parts();
auto *gc = lwcollection_construct_empty(COLLECTIONTYPE, 0, m_has_z, m_has_m);
for (uoffset_t i = 0; i < parts->size(); i++) {
auto part = parts->Get(i);
GeometryReader reader { part, part->type(), m_has_z, m_has_m };
const auto g = reader.read();
lwcollection_add_lwgeom(gc, g);
}
return gc;
}
LWGEOM *GeometryReader::read()
{
// nested types
switch (m_geometry_type) {
case GeometryType::GeometryCollection: return (LWGEOM *) readGeometryCollection();
case GeometryType::MultiPolygon: return (LWGEOM *) readMultiPolygon();
/*case GeometryType::CompoundCurve: return readCompoundCurve();
case GeometryType::CurvePolygon: return readCurvePolygon();
case GeometryType::MultiCurve: return readMultiCurve();
case GeometryType::MultiSurface: return readMultiSurface();
case GeometryType::PolyhedralSurface: return readPolyhedralSurface();*/
default: break;
}
// if not nested must have geometry data
const auto pXy = m_geometry->xy();
const auto xySize = pXy->size();
m_length = xySize / 2;
switch (m_geometry_type) {
case GeometryType::Point: return (LWGEOM *) readPoint();
case GeometryType::MultiPoint: return (LWGEOM *) readMultiPoint();
case GeometryType::LineString: return (LWGEOM *) readLineString();
case GeometryType::MultiLineString: return (LWGEOM *) readMultiLineString();
case GeometryType::Polygon: return (LWGEOM *) readPolygon();
/*
case GeometryType::CircularString: return readSimpleCurve<OGRCircularString>(true);
case GeometryType::Triangle: return readTriangle();
case GeometryType::TIN: return readTIN();
*/
default:
lwerror("flatgeobuf: GeometryReader::read: Unknown type %d", (int) m_geometry_type);
}
return nullptr;
}

80
deps/flatgeobuf/geometryreader.h vendored Normal file
View File

@ -0,0 +1,80 @@
/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PostGIS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
*
**********************************************************************
*
* Copyright 2021 Björn Harrtell
*
**********************************************************************/
#ifndef FLATGEOBUF_GEOMETRYREADER_H
#define FLATGEOBUF_GEOMETRYREADER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lwgeom_log.h"
#include "liblwgeom.h"
#ifdef __cplusplus
}
#endif
#include "feature_generated.h"
namespace FlatGeobuf {
class GeometryReader {
private:
const FlatGeobuf::Geometry *m_geometry;
FlatGeobuf::GeometryType m_geometry_type;
bool m_has_z;
bool m_has_m;
uint32_t m_length = 0;
uint32_t m_offset = 0;
LWPOINT *readPoint();
LWMPOINT *readMultiPoint();
LWLINE *readLineString();
LWMLINE *readMultiLineString();
LWPOLY *readPolygon();
LWMPOLY *readMultiPolygon();
LWCOLLECTION *readGeometryCollection();
POINTARRAY *readPA();
public:
GeometryReader(
const FlatGeobuf::Geometry *geometry,
FlatGeobuf::GeometryType geometry_type,
bool has_z,
bool has_m) :
m_geometry (geometry),
m_geometry_type (geometry_type),
m_has_z (has_z),
m_has_m (has_m)
{ }
LWGEOM *read();
};
}
#endif /* FLATGEOBUF_GEOMETRYREADER_H */

198
deps/flatgeobuf/geometrywriter.cpp vendored Normal file
View File

@ -0,0 +1,198 @@
/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PostGIS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
*
**********************************************************************
*
* Copyright 2021 Björn Harrtell
*
**********************************************************************/
#include "geometrywriter.h"
using namespace FlatGeobuf;
using namespace flatbuffers;
const GeometryType GeometryWriter::get_geometrytype(const LWGEOM *lwgeom)
{
int type = lwgeom->type;
switch (type)
{
case POINTTYPE:
return GeometryType::Point;
case LINETYPE:
return GeometryType::LineString;
case TRIANGLETYPE:
return GeometryType::Triangle;
case POLYGONTYPE:
return GeometryType::Polygon;
case MULTIPOINTTYPE:
return GeometryType::MultiPoint;
case MULTILINETYPE:
return GeometryType::MultiLineString;
case MULTIPOLYGONTYPE:
return GeometryType::MultiPolygon;
case TINTYPE:
case COLLECTIONTYPE:
return GeometryType::GeometryCollection;
default:
lwerror("flatgeobuf: get_geometrytype: '%s' geometry type not supported",
lwtype_name(type));
return GeometryType::Unknown;
}
}
void GeometryWriter::writePoint(const LWPOINT *p)
{
writePA(p->point);
}
void GeometryWriter::writeMultiPoint(const LWMPOINT *mp)
{
writePA(lwline_from_lwmpoint(0, mp)->points);
}
void GeometryWriter::writeLineString(const LWLINE *l)
{
writePA(l->points);
}
void GeometryWriter::writeMultiLineString(const LWMLINE *ml)
{
uint32_t ngeoms = ml->ngeoms;
if (ngeoms == 1)
return writePA(ml->geoms[0]->points);
POINTARRAY **ppa = (POINTARRAY **) lwalloc(sizeof(POINTARRAY *) * ngeoms);
for (uint32_t i = 0; i < ngeoms; i++)
ppa[i] = ml->geoms[i]->points;
writePPA(ppa, ngeoms);
}
void GeometryWriter::writePolygon(const LWPOLY *p)
{
writePPA(p->rings, p->nrings);
}
const Offset<Geometry> GeometryWriter::writeMultiPolygon(const LWMPOLY *mp, int depth)
{
std::vector<Offset<Geometry>> parts;
for (uint32_t i = 0; i < mp->ngeoms; i++)
{
auto part = mp->geoms[i];
if (part->nrings != 0)
{
GeometryWriter writer { m_fbb, (LWGEOM *) part, GeometryType::Polygon, m_has_z, m_has_m };
parts.push_back(writer.write(depth + 1));
}
}
return CreateGeometryDirect(m_fbb, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, m_geometry_type, &parts);
}
const Offset<Geometry> GeometryWriter::writeGeometryCollection(const LWCOLLECTION *gc, int depth)
{
std::vector<Offset<Geometry>> parts;
for (uint32_t i = 0; i < gc->ngeoms; i++)
{
auto part = gc->geoms[i];
auto geometry_type = get_geometrytype(part);
GeometryWriter writer { m_fbb, part, geometry_type, m_has_z, m_has_m };
parts.push_back(writer.write(depth + 1));
}
return CreateGeometryDirect(m_fbb, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, m_geometry_type, &parts);
}
void GeometryWriter::writePA(POINTARRAY *pa)
{
POINT4D pt;
for (uint32_t i = 0; i < pa->npoints; i++) {
getPoint4d_p(pa, i, &pt);
m_xy.push_back(pt.x);
m_xy.push_back(pt.y);
if (m_has_z)
m_z.push_back(pt.z);
if (m_has_m)
m_m.push_back(pt.m);
}
}
void GeometryWriter::writePPA(POINTARRAY **ppa, uint32_t len)
{
if (len == 0)
return;
POINTARRAY *pa = ppa[0];
writePA(pa);
if (len > 1) {
uint32_t e = pa->npoints;
m_ends.push_back(e);
for (uint32_t i = 1; i < len; i++) {
pa = ppa[i];
writePA(pa);
m_ends.push_back(e += pa->npoints);
}
}
}
const Offset<Geometry> GeometryWriter::write(int depth)
{
bool unknownGeometryType = false;
if (depth == 0 && m_geometry_type == GeometryType::Unknown) {
m_geometry_type = get_geometrytype(m_lwgeom);
unknownGeometryType = true;
}
switch (m_geometry_type) {
case GeometryType::Point:
writePoint((LWPOINT *) m_lwgeom); break;
case GeometryType::MultiPoint:
writeMultiPoint((LWMPOINT *) m_lwgeom); break;
case GeometryType::LineString:
writeLineString((LWLINE *) m_lwgeom); break;
case GeometryType::MultiLineString:
writeMultiLineString((LWMLINE *) m_lwgeom); break;
case GeometryType::Polygon:
writePolygon((LWPOLY *) m_lwgeom); break;
case GeometryType::MultiPolygon:
return writeMultiPolygon((LWMPOLY *) m_lwgeom, depth);
case GeometryType::GeometryCollection:
return writeGeometryCollection((LWCOLLECTION *) m_lwgeom, depth);
/*case GeometryType::CircularString:
writeSimpleCurve(m_ogrGeometry->toCircularString()); break;
case GeometryType::CompoundCurve:
return writeCompoundCurve(m_ogrGeometry->toCompoundCurve(), depth);
case GeometryType::CurvePolygon:
return writeCurvePolygon(m_ogrGeometry->toCurvePolygon(), depth);
case GeometryType::MultiCurve:
return writeGeometryCollection(m_ogrGeometry->toMultiCurve(), depth);
case GeometryType::MultiSurface:
return writeGeometryCollection(m_ogrGeometry->toMultiSurface(), depth);
case GeometryType::PolyhedralSurface:
return writePolyhedralSurface(m_ogrGeometry->toPolyhedralSurface(), depth);
case GeometryType::Triangle:
writePolygon(m_ogrGeometry->toTriangle()); break;
case GeometryType::TIN:
writeTIN(m_ogrGeometry->toTriangulatedSurface()); break;*/
default:
lwerror("flatgeobuf: GeometryWriter::write: '%s' geometry type not supported",
lwtype_name(m_lwgeom->type));
return 0;
}
const auto pEnds = m_ends.empty() ? nullptr : &m_ends;
const auto pXy = m_xy.empty() ? nullptr : &m_xy;
const auto pZ = m_z.empty() ? nullptr : &m_z;
const auto pM = m_m.empty() ? nullptr : &m_m;
const auto geometryType = depth > 0 || unknownGeometryType ? m_geometry_type : GeometryType::Unknown;
return FlatGeobuf::CreateGeometryDirect(m_fbb, pEnds, pXy, pZ, pM, nullptr, nullptr, geometryType);
}

92
deps/flatgeobuf/geometrywriter.h vendored Normal file
View File

@ -0,0 +1,92 @@
/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or