diff --git a/CMakeLists.txt b/CMakeLists.txt index bf95c8e2..fbada006 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required( VERSION 2.8 ) project( SFCGAL ) set( CMAKE_DEBUG_POSTFIX "d" ) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) # # Cmake policies diff --git a/src/Geometry.cpp b/src/Geometry.cpp index a8c8722d..a6c891fe 100644 --- a/src/Geometry.cpp +++ b/src/Geometry.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,14 @@ Geometry::asText(const int &numDecimals) const -> std::string return oss.str(); } +auto +Geometry::asWkb(boost::endian::order wkbOrder, bool asHex) const -> std::string +{ + std::ostringstream oss; + detail::io::WkbWriter writer(oss); + writer.write(*this, wkbOrder, asHex); + return oss.str(); +} /// /// /// diff --git a/src/Geometry.h b/src/Geometry.h index f34d4ae9..197ab9da 100644 --- a/src/Geometry.h +++ b/src/Geometry.h @@ -7,6 +7,7 @@ #include +#include #include #include @@ -46,6 +47,10 @@ class ConstGeometryVisitor; namespace SFCGAL { +const uint32_t wkbSRID = 0x20000000; +const uint32_t wkbM = 0x40000000; +const uint32_t wkbZ = 0x80000000; + /** * [OGC/SFA]8.2.3 "A common list of codes for geometric types" * @@ -73,7 +78,7 @@ enum GeometryType { // TYPE_SURFACE = 14, //abstract TYPE_POLYHEDRALSURFACE = 15, TYPE_TRIANGULATEDSURFACE = 16, - TYPE_TRIANGLE = 17, + TYPE_TRIANGLE = 17, //-- not official codes TYPE_SOLID = 101, @@ -194,6 +199,12 @@ class SFCGAL_API Geometry { std::string asText(const int &numDecimals = -1) const; + /** + * [OGC/SFA]returns the WKB string + */ + std::string + asWkb(boost::endian::order wkbOrder = boost::endian::order::native, + bool asHex = false) const; /** * [OGC/SFA]Returns a polygon representing the BBOX of the geometry * @todo In order to adapt to 3D, would be better to define an "Envelope diff --git a/src/PreparedGeometry.cpp b/src/PreparedGeometry.cpp index 244340df..25f63f8b 100644 --- a/src/PreparedGeometry.cpp +++ b/src/PreparedGeometry.cpp @@ -4,6 +4,7 @@ #include +#include #include namespace SFCGAL { @@ -83,4 +84,15 @@ PreparedGeometry::asEWKT(const int &numDecimals) const -> std::string writer.write(*_geometry, exactWrite); return oss.str(); } + +auto +PreparedGeometry::asEWKB(boost::endian::order wkbOrder, bool asHex) const + -> std::string +{ + std::ostringstream oss; + detail::io::WkbWriter writer(oss); + writer.write(*_geometry, _srid, wkbOrder, asHex); + return oss.str(); +} + } // namespace SFCGAL diff --git a/src/PreparedGeometry.h b/src/PreparedGeometry.h index c7427137..da194cdc 100644 --- a/src/PreparedGeometry.h +++ b/src/PreparedGeometry.h @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -101,6 +102,10 @@ class SFCGAL_API PreparedGeometry : public boost::noncopyable { std::string asEWKT(const int &numDecimals = -1) const; + auto + asEWKB(boost::endian::order wkbOrder = boost::endian::order::native, + bool asHex = false) const -> std::string; + /** * Serializer */ diff --git a/src/detail/io/WkbReader.cpp b/src/detail/io/WkbReader.cpp new file mode 100644 index 00000000..25b02ea5 --- /dev/null +++ b/src/detail/io/WkbReader.cpp @@ -0,0 +1,217 @@ +// Copyright (c) 2023-2023, Oslandia. +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SFCGAL::detail::io { + +/** + * Read Point content from wkb + */ +auto +WkbReader::readInnerPoint() -> Point +{ + double x{read()}; + double y{read()}; + + if (!(std::isfinite(x) && std::isfinite(y))) { + return {}; + } + if (_is3D && _isMeasured) { + double z{read()}; + double m{read()}; + + if (!(std::isfinite(z) && std::isfinite(m))) { + return {}; + } + return SFCGAL::Point{x, y, z, m}; + } + if (_is3D) { + double z{read()}; + if (!(std::isfinite(z))) { + return {}; + } + return SFCGAL::Point{x, y, z}; + } + if (_isMeasured) { + + double m{read()}; + if (!(std::isfinite(m))) { + return {}; + } + SFCGAL::Point result{x, y}; + result.setM(m); + return result; + } + return SFCGAL::Point{x, y}; +} + +/** + * Read LineString content from wkb + */ +auto +WkbReader::readInnerLineString() -> LineString +{ + SFCGAL::LineString result; + try { + const uint32_t numPoints{read()}; + for (uint32_t i = 0; i < numPoints; ++i) { + result.addPoint(readInnerPoint()); + } + } catch (std::exception &e) { + std::cerr << e.what(); + return {}; + } + return result; +} + +/** + * Read Polygon content from wkb + */ +auto +WkbReader::readInnerPolygon() -> Polygon +{ + SFCGAL::Polygon result; + try { + const uint32_t numRings{read()}; + for (uint32_t i = 0; i < numRings; ++i) { + SFCGAL::LineString ls{readInnerLineString()}; + + if (i == 0) { + result.setExteriorRing(ls); + } else { + result.addInteriorRing(ls); + } + } + } catch (std::exception &e) { + std::cerr << e.what(); + return {}; + } + return result; +} + +/** + * Read Triangle content from wkb + */ +auto +WkbReader::readInnerTriangle() -> Triangle +{ + try { + SFCGAL::Polygon poly{readInnerPolygon()}; + if (poly.isEmpty()) { + return {}; + } + + SFCGAL::LineString geom{poly.exteriorRing()}; + if (geom.isEmpty()) { + return {}; + } + + return SFCGAL::Triangle{geom.pointN(0), geom.pointN(1), geom.pointN(2)}; + } catch (std::exception &e) { + std::cerr << e.what(); + } + return {}; +} + +/** + * Read MultiGeometries content from wkb + */ +template +auto +WkbReader::readInnerMultiGeometries() -> M +{ + M result; + try { + const uint32_t numGeoms{read()}; + for (uint32_t i = 0; i < numGeoms; ++i) { + readWkb(); + G geom{_geometry->template as()}; + result.addGeometry(geom); + } + } catch (std::exception &e) { + std::cerr << e.what(); + return {}; + } + return result; +} + +/** + * Read GeometryCollection content from wkb + */ +auto +WkbReader::readInnerGeometryCollection() -> GeometryCollection +{ + SFCGAL::GeometryCollection result; + try { + const uint32_t numGeoms{read()}; + for (uint32_t i = 0; i < numGeoms; ++i) { + readWkb(); + result.addGeometry(_geometry.release()); + } + } catch (std::exception &e) { + std::cerr << e.what(); + return {}; + } + return result; +} + +/** + * Read TriangulatedSurface content from wkb + */ +auto +WkbReader::readInnerTriangulatedSurface() -> TriangulatedSurface +{ + SFCGAL::TriangulatedSurface result; + try { + const uint32_t numGeoms{read()}; + for (uint32_t i = 0; i < numGeoms; ++i) { + readWkb(); + SFCGAL::Triangle geom{_geometry->as()}; + result.addTriangle(geom); + } + } catch (std::exception &e) { + std::cerr << e.what(); + return {}; + } + return result; +} + +/** + * Read PolyhedralSurface content from wkb + */ +auto +WkbReader::readInnerPolyhedralSurface() -> PolyhedralSurface +{ + std::vector geoms; + try { + const uint32_t numGeoms{read()}; + for (uint32_t i = 0; i < numGeoms; ++i) { + readWkb(); + geoms.push_back(_geometry->as()); + } + } catch (std::exception &e) { + std::cerr << e.what(); + return {}; + } + SFCGAL::PolyhedralSurface result{geoms}; + return result; +} + +} // namespace SFCGAL::detail::io diff --git a/src/detail/io/WkbReader.h b/src/detail/io/WkbReader.h new file mode 100644 index 00000000..62453423 --- /dev/null +++ b/src/detail/io/WkbReader.h @@ -0,0 +1,321 @@ +// Copyright (c) 2023-2023, Oslandia. +// SPDX-License-Identifier: LGPL-2.0-or-later + +#ifndef _SFCGAL_IO_WKBREADER_H_ +#define _SFCGAL_IO_WKBREADER_H_ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include // don't use bit, since it requires c++20 + +// +namespace SFCGAL::detail::io { + +/** + * read WKB geometry + * + */ +class SFCGAL_API WkbReader { +public: + /** + * read WKB from input stream + */ + WkbReader(std::istream &wkbHexString) : _reader(wkbHexString) {} + + auto + readWkb() -> void + { + // wkbOrder + std::byte wkbOrder{read()}; + _swapEndian = + boost::endian::order::native == boost::endian::order(wkbOrder); + + _geometry = readGeometry(); + } + + /** + * Returns the geometry from the (E)WKB + * + * Must be used after readWkb + */ + auto + geometry() -> std::unique_ptr + { + return std::move(_geometry); + } + + /** + * Returns the prepared geometry from the (E)WKB + * + * Must be used after readWkb + */ + auto + preparedGeometry() -> std::unique_ptr + { + return std::make_unique(std::move(_geometry), + _srid); + } + + /** + * Returns the srid from the (E)WKB + * + * Must be used after readWkb + */ + [[nodiscard]] auto + srid() const -> srid_t + { + return _srid; + } + +private: + /** + * Convenient templated method to read bytes from _wkbData + */ + template + auto + read() -> T + { + + const size_t nbElements = 2; + const size_t sizeType = sizeof(T); + const size_t totalBytesToRead = nbElements * sizeType; + std::string buffer(totalBytesToRead, '\0'); + _reader.readBytes(buffer, totalBytesToRead); + const int base = 16; + union { + std::array byteArray; + T d; + }; + + for (size_t i = 0; i < sizeType; i++) { + size_t chunkPos = nbElements * i; + std::string byteStr = buffer.substr(chunkPos, nbElements); + byteArray[i] = static_cast(std::stoi(byteStr, nullptr, base)); + } + + _index += sizeType * nbElements; + return d; + } + + /** + * + */ + auto + readGeometry() -> std::unique_ptr + { + GeometryType geometryType = readGeometryType(); + return readGeometryData(geometryType); + } + + /** + * + * Read the geometry type from (E)WKB and transform it + * to SFCGAL one. + * + */ + auto + readGeometryType() -> GeometryType + { + auto geometryType = read(); + + if (_isEWKB || ((geometryType & wkbSRID) == wkbSRID)) { + if (!_isEWKB) { + readSRID(); + _isEWKB = true; + } + + if ((geometryType & wkbZ) == wkbZ) { + _is3D = true; + } + if ((geometryType & wkbM) == wkbM) { + _isMeasured = true; + } + geometryType &= 0x0FFFFFFF; + } else { + if (geometryType >= COORDINATE_XYZM) { + _is3D = true; + _isMeasured = true; + geometryType -= COORDINATE_XYZM; + } else if (geometryType >= COORDINATE_XYM) { + _is3D = false; + _isMeasured = true; + geometryType -= COORDINATE_XYM; + } else if (geometryType >= COORDINATE_XYZ) { + _is3D = true; + _isMeasured = false; + geometryType -= COORDINATE_XYZ; + } + } + return static_cast(geometryType); + } + + /** + * Main methods to dispatch reading methods according to the geometry type + */ + auto + readGeometryData(GeometryType geometryType) -> std::unique_ptr + { + switch (geometryType) { + case TYPE_POINT: + return std::unique_ptr{readInnerPoint().clone()}; + + case TYPE_LINESTRING: + return std::unique_ptr(readInnerLineString().clone()); + + case TYPE_POLYGON: + return std::unique_ptr(readInnerPolygon().clone()); + + case TYPE_GEOMETRYCOLLECTION: + return std::unique_ptr( + readInnerGeometryCollection().clone()); + + case TYPE_MULTIPOINT: + return std::unique_ptr( + readInnerMultiGeometries().clone()); + + case TYPE_MULTILINESTRING: + return std::unique_ptr( + readInnerMultiGeometries().clone()); + + case TYPE_MULTIPOLYGON: + return std::unique_ptr( + readInnerMultiGeometries().clone()); + + case TYPE_TRIANGLE: + return std::unique_ptr(readInnerTriangle().clone()); + + case TYPE_TRIANGULATEDSURFACE: + return std::unique_ptr( + readInnerTriangulatedSurface().clone()); + + case TYPE_POLYHEDRALSURFACE: + return std::unique_ptr( + readInnerPolyhedralSurface().clone()); + + default: + std::ostringstream oss; + oss << "WkbWriter : '" << geometryType << "' is not supported"; + std::cerr << oss.str() << std::endl; + + return {}; + } + } + + /** + * Read an SRID, if present + */ + auto + readSRID() -> void + { + _srid = read(); + } + + /** + * Read Point content from wkb + */ + auto + readInnerPoint() -> Point; + + /** + * Read LineString content from wkb + */ + auto + readInnerLineString() -> LineString; + + /** + * Read Polygon content from wkb + */ + auto + readInnerPolygon() -> Polygon; + + /** + * Read MultiGeometries (MultiPoint, MultiLineString, MultiPolygon content + * from Wkb + */ + template + auto + readInnerMultiGeometries() -> M; + + /** + * Read Triangle content from wkb + */ + auto + readInnerTriangle() -> Triangle; + + /** + * Read GeometryCollection content from wkb + */ + auto + readInnerGeometryCollection() -> GeometryCollection; + + /** + * Read TriangulatedSurface content from wkb + */ + auto + readInnerTriangulatedSurface() -> TriangulatedSurface; + + /** + * Read PolyhedralSurface content from wkb + */ + auto + readInnerPolyhedralSurface() -> PolyhedralSurface; + + /** + * actually reading 3D ? + */ + bool _is3D = false; + /** + * actually reading Measured ? + */ + bool _isMeasured = false; + + /** + * wkb data + */ + tools::InputStreamReader _reader; + + /** + * is needed to swap bytes + */ + bool _swapEndian = false; + + /** + * sentinel parsing the _wkbData + */ + std::streamoff _index = 0; + + /** + * SRID value from EWKB + */ + srid_t _srid = 0; + + /** + * flag if the _wkbData is an EWKB or simple WKB + */ + bool _isEWKB = false; + /** + * The geometry from the WKB + */ + std::unique_ptr _geometry; +}; + +} // namespace SFCGAL::detail::io + +#endif diff --git a/src/detail/io/WkbWriter.cpp b/src/detail/io/WkbWriter.cpp new file mode 100644 index 00000000..3a99c465 --- /dev/null +++ b/src/detail/io/WkbWriter.cpp @@ -0,0 +1,295 @@ +// Copyright (c) 2023-2023, Oslandia. +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include +#include // don't use bit, since it requires c++20 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace SFCGAL::detail::io { + +/// +/// +/// +void +WkbWriter::writeRec(const Geometry &g, boost::endian::order wkbOrder) +{ + switch (g.geometryTypeId()) { + case TYPE_POINT: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_LINESTRING: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_POLYGON: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_GEOMETRYCOLLECTION: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_MULTIPOINT: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_MULTILINESTRING: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_MULTIPOLYGON: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_TRIANGLE: + writeInner(g.as(), wkbOrder); + return; + + case TYPE_TRIANGULATEDSURFACE: + writeInner(g.as(), + wkbOrder); + return; + + case TYPE_POLYHEDRALSURFACE: + writeInner(g.as(), wkbOrder); + return; + + default: + std::ostringstream oss; + oss << "WkbWriter : '" << g.geometryType() << "' is not supported"; + BOOST_THROW_EXCEPTION(std::runtime_error(oss.str())); + } +} + +void +WkbWriter::write(const Geometry &g, const srid_t &srid, + boost::endian::order wkbOrder, bool asHex) +{ + + _useSrid = true; + _isEWKB = true; + _srid = srid; + if (asHex) { + _prefix = "\\x"; + } + + write(g, wkbOrder); +} + +/// +/// +/// +void +WkbWriter::write(const Geometry &g, boost::endian::order wkbOrder, bool asHex) +{ + if (asHex) { + _prefix = "\\x"; + } + writeRec(g, wkbOrder); +} + +/// +/// +/// +void +WkbWriter::writeCoordinate(const Point &g, boost::endian::order wkbOrder) +{ + // x + toByte(CGAL::to_double(g.x()), wkbOrder); + + // y + toByte(CGAL::to_double(g.y()), wkbOrder); + + // z + if (g.is3D()) { + toByte(CGAL::to_double(g.z()), wkbOrder); + } + + // m coordinate + if (g.isMeasured()) { + toByte(CGAL::to_double(g.m()), wkbOrder); + } +} + +void +WkbWriter::writeGeometryType(const Geometry &g, boost::endian::order wkbOrder) +{ + + if (_isEWKB) { + + uint32_t ewkbtype = g.geometryTypeId(); + + if (g.is3D()) { + ewkbtype |= wkbZ; + } + if (g.isMeasured()) { + ewkbtype |= wkbM; + } + if (_useSrid) { + ewkbtype |= wkbSRID; + } + toByte(ewkbtype, wkbOrder); + + if (_useSrid) { + toByte(_srid, wkbOrder); + + // once srid defined and written, we write geometry type without it + // so "disable" it. + _useSrid = false; + } + } else { + toByte(static_cast(g.geometryTypeId() + + static_cast(g.is3D()) * COORDINATE_XYZ + + static_cast(g.isMeasured()) * + COORDINATE_XYM), + wkbOrder); + } +} + +/// +/// +/// +void +WkbWriter::writeInner(const Point &g, boost::endian::order wkbOrder) +{ + // Endianness + toStream(std::array{static_cast(wkbOrder)}); + + // WkbType + writeGeometryType(g, wkbOrder); + + if (g.isEmpty()) { + toByte(std::numeric_limits::quiet_NaN(), wkbOrder); + toByte(std::numeric_limits::quiet_NaN(), wkbOrder); + if (g.is3D()) { + toByte(std::numeric_limits::quiet_NaN(), wkbOrder); + } + if (g.isMeasured()) { + toByte(std::numeric_limits::quiet_NaN(), wkbOrder); + } + } else { + writeCoordinate(g, wkbOrder); + } +} + +/// +/// +/// +void +WkbWriter::writeInner(const LineString &g, boost::endian::order wkbOrder) +{ + // Endianness + toStream(std::array{static_cast(wkbOrder)}); + + // WkbType + writeGeometryType(g, wkbOrder); + + writeInnerRing(g, wkbOrder); +} +void +WkbWriter::writeInnerRing(const LineString &g, boost::endian::order wkbOrder) +{ + toByte(static_cast(g.numPoints()), wkbOrder); + + for (size_t i = 0; i < g.numPoints(); i++) { + writeCoordinate(g.pointN(i), wkbOrder); + } +} + +/// +/// +/// +void +WkbWriter::writeInner(const Polygon &g, boost::endian::order wkbOrder) +{ + // Endianness + toStream(std::array{static_cast(wkbOrder)}); + + // WkbType + writeGeometryType(g, wkbOrder); + + toByte(static_cast(g.numRings()), wkbOrder); + + writeInnerRing(g.exteriorRing(), wkbOrder); + for (size_t i = 0; i < g.numInteriorRings(); i++) { + writeInnerRing(g.interiorRingN(i), wkbOrder); + } +} + +/// +/// +/// +void +WkbWriter::writeInner(const Triangle &g, boost::endian::order wkbOrder) +{ + // Endianness + toStream(std::array{static_cast(wkbOrder)}); + + // WkbType + writeGeometryType(g, wkbOrder); + + if (!g.isEmpty()) { + // One Ring + toByte(static_cast(1), wkbOrder); + // 4 points + toByte(static_cast(4), wkbOrder); + for (int i = 0; i < 4; i++) { + writeCoordinate(g.vertex(i), wkbOrder); + } + } +} + +void +WkbWriter::writeInner(const GeometryCollection &g, + boost::endian::order wkbOrder) +{ + // Endianness + toStream(std::array{static_cast(wkbOrder)}); + + // WkbType + writeGeometryType(g, wkbOrder); + + // Number of Geometries + toByte(static_cast(g.numGeometries()), wkbOrder); + + for (size_t i = 0; i < g.numGeometries(); i++) { + writeRec(g.geometryN(i), wkbOrder); + } +} + +template +void +WkbWriter::writeInner(const M &g, boost::endian::order wkbOrder) +{ + // Endianness + toStream(std::array{static_cast(wkbOrder)}); + + // WkbType + writeGeometryType(g, wkbOrder); + + // Number of Geometries + toByte(static_cast(g.numGeometries()), wkbOrder); + + for (size_t i = 0; i < g.numGeometries(); i++) { + writeInner(g.geometryN(i).template as(), wkbOrder); + } +} + +} // namespace SFCGAL::detail::io diff --git a/src/detail/io/WkbWriter.h b/src/detail/io/WkbWriter.h new file mode 100644 index 00000000..c05a5b8c --- /dev/null +++ b/src/detail/io/WkbWriter.h @@ -0,0 +1,153 @@ +// Copyright (c) 2023-2023, Oslandia. +// SPDX-License-Identifier: LGPL-2.0-or-later + +#ifndef _SFCGAL_IO_WKBWRITER_H_ +#define _SFCGAL_IO_WKBWRITER_H_ + +#include +#include +#include +#include +#include + +#include +#include + +using srid_t = uint32_t; + +namespace SFCGAL::detail::io { + +/** + * Writer for WKB + * + */ +class SFCGAL_API WkbWriter { +public: + WkbWriter(std::ostream &s) : _s(s){}; + + /** + * write WKB for a geometry + * wkbOrder is the native endianness by default. + */ + void + write(const Geometry &g, + boost::endian::order wkbOrder = boost::endian::order::native, + bool asHex = false); + + /** + * write EWKB for a geometry + * wkbOrder is the native endianness by default. + */ + void + write(const Geometry &g, const srid_t &srid, + boost::endian::order wkbOrder = boost::endian::order::native, + bool asHex = false); + +private: + /** + * Dedicated method to write the geometry type into _wkb data + */ + void + writeGeometryType(const Geometry &g, boost::endian::order wkbOrder = + boost::endian::order::native); + + /** + * Dedicated method to write Point into _wkb data + */ + void + writeInner(const Point &g, + boost::endian::order wkbOrder = boost::endian::order::native); + + /** + * Dedicated method to write LineString into _wkb data + */ + void + writeInner(const LineString &g, + boost::endian::order wkbOrder = boost::endian::order::native); + /** + * Dedicated method to write Ring into _wkb data + * + * This method is shared by LineString and Polygon. + */ + void + writeInnerRing(const LineString &g, + boost::endian::order wkbOrder = boost::endian::order::native); + + /** + * Dedicated method to write Polygon into _wkb data + */ + void + writeInner(const Polygon &g, + boost::endian::order wkbOrder = boost::endian::order::native); + + /** + * Dedicated method to write GeometryCollection into _wkb data + */ + void + writeInner(const GeometryCollection &g, + boost::endian::order wkbOrder = boost::endian::order::native); + + /** + * Dedicated method to write Multi Geometries into _wkb data + * Multi Geometries are: MultiPoint, MultiLineString, MultiPolygon, + * PolyhedralSurface and TriangulatedSurface. + */ + template + void + writeInner(const M &g, boost::endian::order wkbOrder); + + /** + * Dedicated method to write Triangle into _wkb data + */ + void + writeInner(const Triangle &g, + boost::endian::order wkbOrder = boost::endian::order::native); + + /** + * Dedicated method to write Point into _wkb data + */ + void + writeCoordinate(const Point &g, + boost::endian::order wkbOrder = boost::endian::order::native); + + /** + * Method to write Geometry into _wkb data + * Only for recursive call use + */ + void + writeRec(const Geometry &g, + boost::endian::order wkbOrder = boost::endian::order::native); + + std::ostream &_s; + + template + auto + toStream(const std::array &arr) -> void + { + for (const std::byte &byteVal : arr) { + _s << _prefix << std::hex << std::setw(2) << std::setfill('0') + << static_cast(byteVal); + } + }; + + template + auto + toByte(const T x, boost::endian::order byteOrder) -> void + { + T y = x; + if (boost::endian::order::native != byteOrder) { + boost::endian::endian_reverse_inplace(y); + } + toStream(*reinterpret_cast *>(&y)); + } + + srid_t _srid; + + bool _useSrid = false; + bool _isEWKB = false; + std::string _prefix; +}; + +} // namespace SFCGAL::detail::io + +#endif diff --git a/src/detail/tools/InputStreamReader.h b/src/detail/tools/InputStreamReader.h index 22bb13fb..0168b759 100644 --- a/src/detail/tools/InputStreamReader.h +++ b/src/detail/tools/InputStreamReader.h @@ -152,6 +152,15 @@ class BasicInputStreamReader { } } + auto + readBytes(std::string &buffer, size_t bytesToRead) -> void + { + begin(); + + _s.read(&buffer[0], bytesToRead); + + commit(); + } /// \brief save input stream state (read position) void begin() diff --git a/src/io/wkb.cpp b/src/io/wkb.cpp new file mode 100644 index 00000000..a9c087df --- /dev/null +++ b/src/io/wkb.cpp @@ -0,0 +1,84 @@ +// Copyright (c) 2012-2013, IGN France. +// Copyright (c) 2012-2023, Oslandia. +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include + +#include +#include +#include +#include + +using namespace SFCGAL::detail::io; + +namespace SFCGAL::io { + +/// +/// +/// +auto +readWkb(std::istream &stream) -> std::unique_ptr +{ + WkbReader wkbReader(stream); + wkbReader.readWkb(); + return wkbReader.geometry(); +} + +/// +/// +/// +auto +readWkb(const std::string &s) -> std::unique_ptr +{ + std::istringstream iss(s); + WkbReader wkbReader(iss); + wkbReader.readWkb(); + return wkbReader.geometry(); +} + +/// +/// +/// +auto +readWkb(const char *str, size_t len) -> std::unique_ptr +{ + CharArrayBuffer buf(str, str + len); + std::istream istr(&buf); + + return readWkb(istr); +} + +/** + * Read a WKB geometry from an input stream + */ +auto +readEwkb(std::istream &stream) -> std::unique_ptr +{ + + WkbReader wkbReader(stream); + wkbReader.readWkb(); + return wkbReader.preparedGeometry(); +} + +auto +readEwkb(const std::string &s) -> std::unique_ptr +{ + std::istringstream iss(s); + WkbReader wkbReader(iss); + wkbReader.readWkb(); + return wkbReader.preparedGeometry(); +} + +/** + * Read a WKB geometry from a char* + */ +auto +readEwkb(const char *str, size_t len) -> std::unique_ptr +{ + CharArrayBuffer buf(str, str + len); + std::istream istr(&buf); + + return readEwkb(istr); +} + +} // namespace SFCGAL::io diff --git a/src/io/wkb.h b/src/io/wkb.h new file mode 100644 index 00000000..87a8c22d --- /dev/null +++ b/src/io/wkb.h @@ -0,0 +1,63 @@ +// Copyright (c) 2012-2013, IGN France. +// Copyright (c) 2012-2023, Oslandia. +// SPDX-License-Identifier: LGPL-2.0-or-later + +#ifndef _SFCGAL_IO_WKB_H_ +#define _SFCGAL_IO_WKB_H_ + +#include + +#include +#include +#include + +namespace SFCGAL { +class Geometry; +class PreparedGeometry; +} // namespace SFCGAL + +namespace SFCGAL { +namespace io { + +// WKB + +/** + * Read a WKB geometry from an input stream + */ +SFCGAL_API auto +readWkb(std::istream &stream) -> std::unique_ptr; +/** + * Read a WKB geometry from a string + */ +SFCGAL_API auto +readWkb(const std::string &s) -> std::unique_ptr; + +/** + * Read a WKB geometry from a char* + */ +SFCGAL_API auto +readWkb(const char *, size_t) -> std::unique_ptr; + +// EWKB + +/** + * Read a EWKB geometry from an input stream + */ +SFCGAL_API auto +readEwkb(std::istream &stream) -> std::unique_ptr; +/** + * Read a EWKB geometry from a string + */ +SFCGAL_API auto +readEwkb(const std::string &s) -> std::unique_ptr; + +/** + * Read a EWKB geometry from a char* + */ +SFCGAL_API auto +readEwkb(const char *, size_t) -> std::unique_ptr; + +} // namespace io +} // namespace SFCGAL + +#endif diff --git a/test/data/EWKB_postgis.txt b/test/data/EWKB_postgis.txt new file mode 100644 index 00000000..cb0c9955 --- /dev/null +++ b/test/data/EWKB_postgis.txt @@ -0,0 +1,146 @@ +01070000206a0f00000200000001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f010300000000000000 +01070000206a0f0000040000000101000000000000000000f03f000000000000004001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f0103000000010000000500000000000000000000000000000000000000000000000000000000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000000000000000000000000104000000020000000101000000000000000000f03f000000000000f03f010100000000000000000000400000000000000040 +01070000206a0f0000020000000101000000000000000000f03f000000000000004001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040 +01070000206a0f0000030000000101000000000000000000f03f000000000000004001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040010700000002000000010100000000000000000008400000000000001040010300000001000000050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000 +01070000206a0f0000030000000101000000000000000000f03f000000000000004001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040010300000001000000050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000 +01070000206a0f0000020000000101000000000000000000f03f00000000000000400101000000000000000000f87f000000000000f87f + + +01070000e06a0f00000300000001010000c0000000000000f03f00000000000000400000000000000840000000000000104001020000c00300000000000000000000000000000000000000000000000000f03f0000000000001040000000000000f03f000000000000f03f00000000000000400000000000001440000000000000004000000000000000400000000000000840000000000000184001030000c0010000000500000000000000000000000000000000000000000000000000f03f0000000000001040000000000000000000000000000008400000000000000040000000000000144000000000000008400000000000000840000000000000084000000000000018400000000000000840000000000000000000000000000010400000000000001c4000000000000000000000000000000000000000000000f03f0000000000001040 + +01070000206a0f000000000000 +01020000a06a0f0000020000000000000000405dc0000000000080404000000000000000400000000000005dc000000000000041400000000000001040 +01020000206a0f00000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040 +01020000206a0f0000020000000000000000001440000000000000204000000000000014400000000000001c40 +01020000206a0f000000000000 +01020000606a0f000003000000000000000000000000000000000000000000000000001040000000000000f03f000000000000f03f0000000000001440000000000000004000000000000000400000000000001840 +01020000606a0f000000000000 +01020000a06a0f0000020000000000000000405dc0000000000080404000000000000000400000000000005dc000000000000041400000000000001040 +01020000a06a0f00000300000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000004000000000000000400000000000000840 +01020000a06a0f000000000000 + +01020000e06a0f0000020000000000000000405dc00000000000804040000000000000004000000000000008400000000000005dc0000000000000414000000000000010400000000000001440 +01020000e06a0f00000300000000000000000000000000000000000000000000000000f03f0000000000001040000000000000f03f000000000000f03f000000000000004000000000000014400000000000000040000000000000004000000000000008400000000000001840 +01020000e06a0f000000000000 +01020000206a0f0000020000000000000000405dc000000000008040400000000000005dc00000000000004140 +01020000606a0f000000000000 +01020000a06a0f000000000000 +01020000a06a0f00000200000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f +01020000e06a0f000000000000 +01050000206a0f00000200000001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040010200000003000000000000000000084000000000000008400000000000001040000000000000104000000000000014400000000000001440 +01050000206a0f000000000000 +01050000606a0f000002000000010200004003000000000000000000000000000000000000000000000000001040000000000000f03f000000000000f03f0000000000001440000000000000004000000000000000400000000000001840010200004003000000000000000000084000000000000008400000000000001c40000000000000104000000000000010400000000000002040000000000000144000000000000014400000000000002240 +01050000606a0f000000000000 +01050000a06a0f00000200000001020000800300000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000004000000000000000400000000000000840010200008003000000000000000000084000000000000008400000000000001040000000000000104000000000000010400000000000001440000000000000144000000000000014400000000000001840 +01050000a06a0f000000000000 + +01050000e06a0f00000200000001020000c00300000000000000000000000000000000000000000000000000f03f0000000000001040000000000000f03f000000000000f03f00000000000000400000000000001440000000000000004000000000000000400000000000000840000000000000184001020000c0030000000000000000000840000000000000084000000000000010400000000000001c4000000000000010400000000000001040000000000000144000000000000020400000000000001440000000000000144000000000000018400000000000002240 +01050000e06a0f000000000000 +01050000606a0f000000000000 +01050000a06a0f000000000000 +01050000e06a0f000000000000 +01040000206a0f0000030000000101000000000000000000000000000000000000000101000000000000000000f03f000000000000f03f010100000000000000000000400000000000000040 +01040000206a0f0000020000000101000000000000000000000000000000000000000101000000000000000000f03f0000000000000040 +01040000206a0f0000020000000101000000000000000000000000000000000000000101000000000000000000f03f0000000000000040 +01040000206a0f000000000000 +01040000606a0f00000200000001010000400000000000000000000000000000000000000000000008400101000040000000000000f03f00000000000000400000000000001440 +01040000606a0f00000300000001010000400000000000000000000000000000000000000000000010400101000040000000000000f03f000000000000f03f00000000000014400101000040000000000000004000000000000000400000000000001840 +01040000606a0f00000200000001010000400000000000000000000000000000000000000000000008400101000040000000000000f03f00000000000000400000000000001440 +01040000606a0f000000000000 +01040000a06a0f000003000000010100008000000000000000000000000000000000000000000000f03f0101000080000000000000f03f000000000000f03f00000000000000400101000080000000000000004000000000000000400000000000000840 +01040000a06a0f00000200000001010000800000000000000000000000000000000000000000000010400101000080000000000000f03f00000000000000400000000000001040 +01040000a06a0f00000200000001010000800000000000000000000000000000000000000000000010400101000080000000000000f03f00000000000000400000000000001040 +01040000a06a0f000000000000 + +01040000e06a0f00000300000001010000c000000000000000000000000000000000000000000000f03f000000000000104001010000c0000000000000f03f000000000000f03f0000000000000040000000000000144001010000c00000000000000040000000000000004000000000000008400000000000001840 +01040000e06a0f00000200000001010000c0000000000000000000000000000000000000000000001040000000000000084001010000c0000000000000f03f000000000000004000000000000010400000000000001440 +01040000e06a0f00000200000001010000c0000000000000000000000000000000000000000000001040000000000000084001010000c0000000000000f03f000000000000004000000000000010400000000000001440 +01040000e06a0f000000000000 +01040000206a0f0000020000000101000000000000000000f03f000000000000f03f0101000000000000000000f87f000000000000f87f +01040000206a0f0000020000000101000000000000000000f87f000000000000f87f0101000000000000000000f87f000000000000f87f +01040000206a0f0000020000000101000000000000000000f87f000000000000f87f0101000000000000000000f03f000000000000f03f +01040000606a0f000000000000 +01040000a06a0f000000000000 +01040000e06a0f000000000000 +01060000206a0f00000200000001030000000100000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000001030000000100000005000000000000000000f03f000000000000f03f000000000000f03f0000000000001040000000000000104000000000000010400000000000001040000000000000f03f000000000000f03f000000000000f03f +01060000206a0f000002000000010300000001000000050000000000000000002440000000000000244000000000000024400000000000002a400000000000002a400000000000002a400000000000002a4000000000000024400000000000002440000000000000244001030000000200000005000000000000000000f03f000000000000f03f000000000000f03f0000000000001040000000000000104000000000000010400000000000001040000000000000f03f000000000000f03f000000000000f03f050000000000000000000040000000000000004000000000000000400000000000000840000000000000084000000000000008400000000000000840000000000000004000000000000000400000000000000040 +01060000206a0f000000000000 +01060000606a0f00000200000001030000400100000005000000000000000000000000000000000000000000000000001040000000000000000000000000000008400000000000001440000000000000084000000000000008400000000000001840000000000000084000000000000000000000000000001c4000000000000000000000000000000000000000000000104001030000400100000005000000000000000000f03f000000000000f03f0000000000002240000000000000f03f000000000000104000000000000024400000000000001040000000000000104000000000000026400000000000001040000000000000f03f0000000000002840000000000000f03f000000000000f03f0000000000002240 +01060000606a0f000000000000 +01060000a06a0f0000020000000103000080010000000500000000000000000000000000000000000000000000000000f03f00000000000000000000000000000840000000000000004000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000104000000000000000000000000000000000000000000000f03f01030000800100000005000000000000000000f03f000000000000f03f0000000000001440000000000000f03f00000000000010400000000000001840000000000000104000000000000010400000000000001c400000000000001040000000000000f03f0000000000002040000000000000f03f000000000000f03f0000000000001440 +01060000a06a0f000000000000 + +01060000e06a0f00000200000001030000c0010000000500000000000000000000000000000000000000000000000000f03f0000000000001040000000000000000000000000000008400000000000000040000000000000144000000000000008400000000000000840000000000000084000000000000018400000000000000840000000000000000000000000000010400000000000001c4000000000000000000000000000000000000000000000f03f000000000000104001030000c00100000005000000000000000000f03f000000000000f03f00000000000014400000000000002040000000000000f03f000000000000104000000000000018400000000000002240000000000000104000000000000010400000000000001c4000000000000024400000000000001040000000000000f03f00000000000020400000000000002640000000000000f03f000000000000f03f00000000000014400000000000002040 +01060000e06a0f000000000000 +01060000606a0f000000000000 +01060000a06a0f000000000000 +01060000e06a0f000000000000 +01010000206a0f000000000000000000400000000000002040 +01010000206a0f000000000000000000400000000000001040 +01010000206a0f0000000000000000f87f000000000000f87f +01010000606a0f0000000000000000f87f000000000000f87f000000000000f87f +01010000606a0f0000000000000000f03f00000000000000400000000000000840 +01010000606a0f0000000000000000144000000000000018400000000000001c40 +01010000a06a0f0000000000000000f03f00000000000000400000000000000840 +01010000a06a0f0000000000000000f87f000000000000f87f000000000000f87f + +01010000e06a0f0000000000000000f87f000000000000f87f000000000000f87f000000000000f87f +01010000606a0f0000000000000000f87f000000000000f87f000000000000f87f +01010000a06a0f0000000000000000f87f000000000000f87f000000000000f87f +01010000e06a0f0000000000000000f87f000000000000f87f000000000000f87f000000000000f87f +01030000206a0f000001000000050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000 +01030000206a0f00000200000005000000000000000000000000000000000000000000000000000000000000000000104000000000000010400000000000001040000000000000104000000000000000000000000000000000000000000000000005000000000000000000f03f000000000000f03f0000000000000840000000000000f03f00000000000008400000000000000840000000000000f03f0000000000000840000000000000f03f000000000000f03f +01030000206a0f000000000000 +01030000606a0f00000100000005000000000000000000000000000000000000000000000000001040000000000000000000000000000008400000000000001440000000000000084000000000000008400000000000001840000000000000084000000000000000000000000000001c40000000000000000000000000000000000000000000001040 +01030000606a0f000000000000 +01030000a06a0f0000010000000500000000000000000000000000000000000000000000000000f03f00000000000000000000000000000840000000000000004000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000104000000000000000000000000000000000000000000000f03f + +01030000a06a0f000000000000 + +01030000e06a0f0000010000000500000000000000000000000000000000000000000000000000f03f0000000000001040000000000000000000000000000008400000000000000040000000000000144000000000000008400000000000000840000000000000084000000000000018400000000000000840000000000000000000000000000010400000000000001c4000000000000000000000000000000000000000000000f03f0000000000001040 +01030000e06a0f000000000000 + + +01030000606a0f000000000000 +01030000a06a0f000000000000 +01030000e06a0f000000000000 +01110000206a0f000000000000 +01110000606a0f000000000000 +01110000a06a0f000000000000 +01110000e06a0f000000000000 +01110000606a0f000000000000 +01110000a06a0f000000000000 +01110000e06a0f000000000000 + +01110000206a0f0000010000000400000000000000000000000000000000000000000000000000144000000000000014400000000000000000000000000000144000000000000000000000000000000000 +01110000a06a0f0000010000000400000000000000000000000000000000000000000000000000f03f00000000000014400000000000001440000000000000144000000000000000000000000000001440000000000000004000000000000000000000000000000000000000000000f03f +01110000606a0f0000010000000400000000000000000000000000000000000000000000000000f03f00000000000014400000000000001440000000000000144000000000000000000000000000001440000000000000004000000000000000000000000000000000000000000000f03f +01110000e06a0f0000010000000400000000000000000000000000000000000000000000000000f03f00000000000000400000000000001440000000000000144000000000000014400000000000000840000000000000000000000000000014400000000000000040000000000000104000000000000000000000000000000000000000000000f03f0000000000000040 +01100000a06a0f000002000000011100008001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f000000000000000000000000000000000000000000000000000000000000000001110000800100000004000000000000000000e03f000000000000e03f000000000000f03f000000000000e03f000000000000f83f000000000000f03f000000000000f83f000000000000f83f000000000000f03f000000000000e03f000000000000e03f000000000000f03f +01100000206a0f00000100000001110000000100000004000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f00000000000000000000000000000000 +01100000206a0f000000000000 +01100000606a0f000000000000 +01100000606a0f000001000000011100004001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000000000000000000000000000000000000000 +01100000a06a0f000000000000 + +01100000a06a0f000001000000011100008001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000000000000000000000000000000000000000 +01100000e06a0f000000000000 +01100000606a0f000000000000 +01100000a06a0f000000000000 +01100000e06a0f000000000000 +010f0000206a0f00000100000001030000000100000005000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f000000000000000000000000000000000000000000000000 +010f0000a06a0f000001000000010300008001000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000000000000000000000000000000000000000000000000000000 +010f0000606a0f000001000000010300004001000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000000000000000000000000000000000000000000000000000000 +010f0000e06a0f00000100000001030000c00100000005000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000040000000000000f03f000000000000f03f00000000000000000000000000000840000000000000f03f000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000f03f +010f0000206a0f00000200000001030000000100000005000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f00000000000000000000000000000000000000000000000001030000000100000005000000000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000004000000000000000400000000000000040000000000000f03f000000000000f03f000000000000f03f +010f0000a06a0f000002000000010300008001000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f0000000000000000000000000000000000000000000000000000000000000000000000000000000001030000800100000005000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000f03f00000000000000400000000000000040000000000000f03f0000000000000040000000000000f03f000000000000f03f000000000000f03f000000000000f03f000000000000f03f +010f0000606a0f0000020000000103000040010000000500000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f0000000000000040000000000000f03f000000000000f03f0000000000000840000000000000f03f0000000000000000000000000000104000000000000000000000000000000000000000000000f03f01030000400100000005000000000000000000f03f000000000000f03f0000000000001440000000000000f03f00000000000000400000000000001840000000000000004000000000000000400000000000001c400000000000000040000000000000f03f0000000000002040000000000000f03f000000000000f03f0000000000001440 +010f0000e06a0f00000200000001030000c00100000005000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000040000000000000f03f000000000000f03f00000000000000000000000000000840000000000000f03f000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000f03f01030000c00100000005000000000000000000f03f000000000000f03f000000000000f03f0000000000001440000000000000f03f0000000000000040000000000000f03f000000000000184000000000000000400000000000000040000000000000f03f0000000000001c400000000000000040000000000000f03f000000000000f03f0000000000002040000000000000f03f000000000000f03f000000000000f03f0000000000001440 +010f0000206a0f000000000000 +010f0000606a0f000000000000 +010f0000a06a0f000000000000 +010f0000e06a0f000000000000 +010f0000a06a0f000000000000 +010f0000606a0f000000000000 +010f0000e06a0f000000000000 + diff --git a/test/data/WKB_expected.txt b/test/data/WKB_expected.txt new file mode 100644 index 00000000..7c471e44 --- /dev/null +++ b/test/data/WKB_expected.txt @@ -0,0 +1,146 @@ +01070000000100000001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f +0107000000040000000101000000000000000000f03f000000000000004001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f0103000000010000000500000000000000000000000000000000000000000000000000000000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000000000000000000000000104000000020000000101000000000000000000f03f000000000000f03f010100000000000000000000400000000000000040 +0107000000020000000101000000000000000000f03f000000000000004001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040 +0107000000030000000101000000000000000000f03f000000000000004001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040010700000002000000010100000000000000000008400000000000001040010300000001000000050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000 +0107000000030000000101000000000000000000f03f000000000000004001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040010300000001000000050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000 +0107000000010000000101000000000000000000f03f0000000000000040 +01ef0300000300000001e903000000000000000008400000000000000840000000000000084001e903000000000000000010400000000000001040000000000000224001e9030000000000000000004000000000000020400000000000000040 +01ef0300000400000001e9030000000000000000f03f0000000000000040000000000000084001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f0000000000000040000000000000004001eb030000010000000500000000000000000000000000000000000000000000000000f03f00000000000000000000000000000840000000000000004000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000104000000000000000000000000000000000000000000000f03f01d40700000200000001d1070000000000000000f03f000000000000f03f000000000000104001d1070000000000000000004000000000000000400000000000001440 +01bf0b00000300000001b90b0000000000000000f03f00000000000000400000000000000840000000000000104001ba0b00000300000000000000000000000000000000000000000000000000f03f0000000000001040000000000000f03f000000000000f03f00000000000000400000000000001440000000000000004000000000000000400000000000000840000000000000184001bb0b0000010000000500000000000000000000000000000000000000000000000000f03f0000000000001040000000000000000000000000000008400000000000000040000000000000144000000000000008400000000000000840000000000000084000000000000018400000000000000840000000000000000000000000000010400000000000001c4000000000000000000000000000000000000000000000f03f0000000000001040 +01bf0b00000300000001b90b0000000000000000f03f00000000000000400000000000000840000000000000104001030000000100000005000000000000000000000000000000000000000000000000000000000000000000104000000000000010400000000000001040000000000000104000000000000000000000000000000000000000000000000001bb0b0000010000000500000000000000000000000000000000000000000000000000f03f0000000000001040000000000000000000000000000008400000000000000040000000000000144000000000000008400000000000000840000000000000084000000000000018400000000000000840000000000000000000000000000010400000000000001c4000000000000000000000000000000000000000000000f03f0000000000001040 +010700000000000000 +01ea030000020000000000000000405dc0000000000080404000000000000000400000000000005dc000000000000041400000000000001040 +01020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040 +0102000000020000000000000000001440000000000000204000000000000014400000000000001c40 +010200000000000000 +01d207000003000000000000000000000000000000000000000000000000001040000000000000f03f000000000000f03f0000000000001440000000000000004000000000000000400000000000001840 +010200000000000000 +01ea030000020000000000000000405dc0000000000080404000000000000000400000000000005dc000000000000041400000000000001040 +01ea0300000300000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000004000000000000000400000000000000840 +010200000000000000 +010200000000000000 +01ba0b0000020000000000000000405dc00000000000804040000000000000004000000000000008400000000000005dc0000000000000414000000000000010400000000000001440 +01ba0b00000300000000000000000000000000000000000000000000000000f03f0000000000001040000000000000f03f000000000000f03f000000000000004000000000000014400000000000000040000000000000004000000000000008400000000000001840 +010200000000000000 +0102000000020000000000000000405dc000000000008040400000000000005dc00000000000004140 +010200000000000000 +010200000000000000 +01ea0300000200000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f +010200000000000000 +01050000000200000001020000000300000000000000000000000000000000000000000000000000f03f000000000000f03f00000000000000400000000000000040010200000003000000000000000000084000000000000008400000000000001040000000000000104000000000000014400000000000001440 +010500000000000000 +01d50700000200000001d207000003000000000000000000000000000000000000000000000000001040000000000000f03f000000000000f03f000000000000144000000000000000400000000000000040000000000000184001d207000003000000000000000000084000000000000008400000000000001c40000000000000104000000000000010400000000000002040000000000000144000000000000014400000000000002240 +010500000000000000 +01ed0300000200000001ea0300000300000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000004000000000000000400000000000000040000000000000084001ea03000003000000000000000000084000000000000008400000000000001040000000000000104000000000000010400000000000001440000000000000144000000000000014400000000000001840 +010500000000000000 +010500000000000000 +01bd0b00000200000001ba0b00000300000000000000000000000000000000000000000000000000f03f0000000000001040000000000000f03f000000000000f03f00000000000000400000000000001440000000000000004000000000000000400000000000000840000000000000184001ba0b0000030000000000000000000840000000000000084000000000000010400000000000001c4000000000000010400000000000001040000000000000144000000000000020400000000000001440000000000000144000000000000018400000000000002240 +010500000000000000 +010500000000000000 +010500000000000000 +010500000000000000 +0104000000030000000101000000000000000000000000000000000000000101000000000000000000f03f000000000000f03f010100000000000000000000400000000000000040 +0104000000020000000101000000000000000000000000000000000000000101000000000000000000f03f0000000000000040 +0104000000020000000101000000000000000000000000000000000000000101000000000000000000f03f0000000000000040 +010400000000000000 +01d40700000200000001d107000000000000000000000000000000000000000000000000084001d1070000000000000000f03f00000000000000400000000000001440 +01d40700000300000001d107000000000000000000000000000000000000000000000000104001d1070000000000000000f03f000000000000f03f000000000000144001d1070000000000000000004000000000000000400000000000001840 +01d40700000200000001d107000000000000000000000000000000000000000000000000084001d1070000000000000000f03f00000000000000400000000000001440 +010400000000000000 +01ec0300000300000001e903000000000000000000000000000000000000000000000000f03f01e9030000000000000000f03f000000000000f03f000000000000004001e9030000000000000000004000000000000000400000000000000840 +01ec0300000200000001e903000000000000000000000000000000000000000000000000104001e9030000000000000000f03f00000000000000400000000000001040 +01ec0300000200000001e903000000000000000000000000000000000000000000000000104001e9030000000000000000f03f00000000000000400000000000001040 +010400000000000000 +010400000000000000 +01bc0b00000300000001b90b000000000000000000000000000000000000000000000000f03f000000000000104001b90b0000000000000000f03f000000000000f03f0000000000000040000000000000144001b90b00000000000000000040000000000000004000000000000008400000000000001840 +01bc0b00000200000001b90b0000000000000000000000000000000000000000000000001040000000000000084001b90b0000000000000000f03f000000000000004000000000000010400000000000001440 +01bc0b00000200000001b90b0000000000000000000000000000000000000000000000001040000000000000084001b90b0000000000000000f03f000000000000004000000000000010400000000000001440 +010400000000000000 +0104000000010000000101000000000000000000f03f000000000000f03f +010400000000000000 +0104000000010000000101000000000000000000f03f000000000000f03f +010400000000000000 +010400000000000000 +010400000000000000 +01060000000200000001030000000100000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000001030000000100000005000000000000000000f03f000000000000f03f000000000000f03f0000000000001040000000000000104000000000000010400000000000001040000000000000f03f000000000000f03f000000000000f03f +010600000002000000010300000001000000050000000000000000002440000000000000244000000000000024400000000000002a400000000000002a400000000000002a400000000000002a4000000000000024400000000000002440000000000000244001030000000200000005000000000000000000f03f000000000000f03f000000000000f03f0000000000001040000000000000104000000000000010400000000000001040000000000000f03f000000000000f03f000000000000f03f050000000000000000000040000000000000004000000000000000400000000000000840000000000000084000000000000008400000000000000840000000000000004000000000000000400000000000000040 +010600000000000000 +01d60700000200000001d30700000100000005000000000000000000000000000000000000000000000000001040000000000000000000000000000008400000000000001440000000000000084000000000000008400000000000001840000000000000084000000000000000000000000000001c4000000000000000000000000000000000000000000000104001d30700000100000005000000000000000000f03f000000000000f03f0000000000002240000000000000f03f000000000000104000000000000024400000000000001040000000000000104000000000000026400000000000001040000000000000f03f0000000000002840000000000000f03f000000000000f03f0000000000002240 +010600000000000000 +01ee0300000200000001eb030000010000000500000000000000000000000000000000000000000000000000f03f00000000000000000000000000000840000000000000004000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000104000000000000000000000000000000000000000000000f03f01eb0300000100000005000000000000000000f03f000000000000f03f0000000000001440000000000000f03f00000000000010400000000000001840000000000000104000000000000010400000000000001c400000000000001040000000000000f03f0000000000002040000000000000f03f000000000000f03f0000000000001440 +010600000000000000 +010600000000000000 +01be0b00000200000001bb0b0000010000000500000000000000000000000000000000000000000000000000f03f0000000000001040000000000000000000000000000008400000000000000040000000000000144000000000000008400000000000000840000000000000084000000000000018400000000000000840000000000000000000000000000010400000000000001c4000000000000000000000000000000000000000000000f03f000000000000104001bb0b00000100000005000000000000000000f03f000000000000f03f00000000000014400000000000002040000000000000f03f000000000000104000000000000018400000000000002240000000000000104000000000000010400000000000001c4000000000000024400000000000001040000000000000f03f00000000000020400000000000002640000000000000f03f000000000000f03f00000000000014400000000000002040 +010600000000000000 +010600000000000000 +010600000000000000 +010600000000000000 +010100000000000000000000400000000000002040 +010100000000000000000000400000000000001040 +0101000000000000000000f87f000000000000f87f +0101000000000000000000f87f000000000000f87f +01d1070000000000000000f03f00000000000000400000000000000840 +01d1070000000000000000144000000000000018400000000000001c40 +01e9030000000000000000f03f00000000000000400000000000000840 +0101000000000000000000f87f000000000000f87f +0101000000000000000000f87f000000000000f87f +0101000000000000000000f87f000000000000f87f +0101000000000000000000f87f000000000000f87f +0101000000000000000000f87f000000000000f87f +0101000000000000000000f87f000000000000f87f +010300000001000000050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000 +01030000000200000005000000000000000000000000000000000000000000000000000000000000000000104000000000000010400000000000001040000000000000104000000000000000000000000000000000000000000000000005000000000000000000f03f000000000000f03f0000000000000840000000000000f03f00000000000008400000000000000840000000000000f03f0000000000000840000000000000f03f000000000000f03f +01030000000100000000000000 +01d30700000100000005000000000000000000000000000000000000000000000000001040000000000000000000000000000008400000000000001440000000000000084000000000000008400000000000001840000000000000084000000000000000000000000000001c40000000000000000000000000000000000000000000001040 +01030000000100000000000000 +01eb030000010000000500000000000000000000000000000000000000000000000000f03f00000000000000000000000000000840000000000000004000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000104000000000000000000000000000000000000000000000f03f +01030000000200000005000000000000000000000000000000000000000000000000000000000000000000244000000000000024400000000000002440000000000000244000000000000000000000000000000000000000000000000005000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000f03f00000000000000400000000000000040000000000000f03f0000000000000040000000000000f03f000000000000f03f000000000000f03f000000000000f03f000000000000f03f +01030000000100000000000000 +01030000000100000000000000 +01bb0b0000010000000500000000000000000000000000000000000000000000000000f03f0000000000001040000000000000000000000000000008400000000000000040000000000000144000000000000008400000000000000840000000000000084000000000000018400000000000000840000000000000000000000000000010400000000000001c4000000000000000000000000000000000000000000000f03f0000000000001040 +01030000000100000000000000 +0103000000020000000000000004000000000000000000f03f000000000000f03f00000000000000400000000000000040000000000000f03f0000000000000040000000000000f03f000000000000f03f +01030000000100000004000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f0000000000000000 +01030000000100000000000000 +01030000000100000000000000 +01030000000100000000000000 +0111000000 +0111000000 +0111000000 +0111000000 +0111000000 +0111000000 +0111000000 +0111000000 +0111000000010000000400000000000000000000000000000000000000000000000000144000000000000014400000000000000000000000000000144000000000000000000000000000000000 +01f9030000010000000400000000000000000000000000000000000000000000000000f03f00000000000014400000000000001440000000000000144000000000000000000000000000001440000000000000004000000000000000000000000000000000000000000000f03f +01e1070000010000000400000000000000000000000000000000000000000000000000f03f00000000000014400000000000001440000000000000144000000000000000000000000000001440000000000000004000000000000000000000000000000000000000000000f03f +01c90b0000010000000400000000000000000000000000000000000000000000000000f03f00000000000000400000000000001440000000000000144000000000000014400000000000000840000000000000000000000000000014400000000000000040000000000000104000000000000000000000000000000000000000000000f03f0000000000000040 +01f80300000200000001f903000001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f000000000000000000000000000000000000000000000000000000000000000001f90300000100000004000000000000000000e03f000000000000e03f000000000000f03f000000000000e03f000000000000f83f000000000000f03f000000000000f83f000000000000f83f000000000000f03f000000000000e03f000000000000e03f000000000000f03f +01100000000100000001110000000100000004000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f00000000000000000000000000000000 +011000000000000000 +011000000000000000 +01e00700000100000001e107000001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000000000000000000000000000000000000000 +011000000000000000 +011000000000000000 +01f80300000100000001f903000001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000000000000000000000000000000000000000 +011000000000000000 +011000000000000000 +011000000000000000 +011000000000000000 +010f0000000100000001030000000100000005000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f000000000000000000000000000000000000000000000000 +01f70300000100000001eb03000001000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000000000000000000000000000000000000000000000000000000 +01df0700000100000001d307000001000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000000000000000000000000000000000000000000000000000000 +01c70b00000100000001bb0b00000100000005000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000040000000000000f03f000000000000f03f00000000000000000000000000000840000000000000f03f000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000f03f +010f0000000200000001030000000100000005000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f00000000000000000000000000000000000000000000000001030000000100000005000000000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000004000000000000000400000000000000040000000000000f03f000000000000f03f000000000000f03f +01f70300000200000001eb03000001000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f0000000000000000000000000000000000000000000000000000000000000000000000000000000001eb0300000100000005000000000000000000f03f000000000000f03f000000000000f03f000000000000f03f0000000000000040000000000000f03f00000000000000400000000000000040000000000000f03f0000000000000040000000000000f03f000000000000f03f000000000000f03f000000000000f03f000000000000f03f +01df0700000200000001d3070000010000000500000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f0000000000000040000000000000f03f000000000000f03f0000000000000840000000000000f03f0000000000000000000000000000104000000000000000000000000000000000000000000000f03f01d30700000100000005000000000000000000f03f000000000000f03f0000000000001440000000000000f03f00000000000000400000000000001840000000000000004000000000000000400000000000001c400000000000000040000000000000f03f0000000000002040000000000000f03f000000000000f03f0000000000001440 +01c70b00000200000001bb0b00000100000005000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000040000000000000f03f000000000000f03f00000000000000000000000000000840000000000000f03f000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000f03f01bb0b00000100000005000000000000000000f03f000000000000f03f000000000000f03f0000000000001440000000000000f03f0000000000000040000000000000f03f000000000000184000000000000000400000000000000040000000000000f03f0000000000001c400000000000000040000000000000f03f000000000000f03f0000000000002040000000000000f03f000000000000f03f000000000000f03f0000000000001440 +010f00000000000000 +010f00000000000000 +010f00000000000000 +010f00000000000000 +010f00000000000000 +010f00000000000000 +010f00000000000000 +010f00000000000000 diff --git a/test/data/WKT.txt b/test/data/WKT.txt new file mode 100644 index 00000000..53cb7b4d --- /dev/null +++ b/test/data/WKT.txt @@ -0,0 +1,146 @@ +GEOMETRYCOLLECTION (LINESTRING (0 0, 1 1), POLYGON EMPTY) +GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 1 1), POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0)), MULTIPOINT ((1 1), (2 2))) +GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 1 1, 2 2)) +GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 1 1, 2 2), GEOMETRYCOLLECTION (POINT (3 4), POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0)))) +GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 1 1, 2 2), POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0))) +GEOMETRYCOLLECTION (POINT (1 2), POINT EMPTY) +GEOMETRYCOLLECTION (POINT (3 3 3), POINTZ (4 4 9), POINT Z (2 8 2), POINT EMPTY) +GEOMETRYCOLLECTION (POINT Z (1 2 3), LINESTRING (0 0, 1 1, 2 2), POLYGON Z ((0 0 1, 0 3 2, 3 3 3, 3 0 4, 0 0 1)), MULTIPOINT M ((1 1 4), (2 2 5))) +GEOMETRYCOLLECTION (POINT ZM (1 2 3 4), LINESTRING ZM (0 0 1 4, 1 1 2 5, 2 2 3 6), POLYGON ZM ((0 0 1 4, 0 3 2 5, 3 3 3 6, 3 0 4 7, 0 0 1 4))) +GEOMETRYCOLLECTION (POINT ZM (1 2 3 4), POINT EMPTY, POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0)), POLYGON ZM ((0 0 1 4, 0 3 2 5, 3 3 3 6, 3 0 4 7, 0 0 1 4)), POLYGON EMPTY) +GEOMETRYCOLLECTION EMPTY +LINESTRING (-117 33 2, -116 34 4) +LINESTRING (0 0, 1 1, 2 2) +LINESTRING (5 8, 5 7) +LINESTRING EMPTY +LINESTRING M (0 0 4, 1 1 5, 2 2 6) +LINESTRING M EMPTY +LINESTRING Z (-117 33 2, -116 34 4) +LINESTRING Z (0 0 1, 1 1 2, 2 2 3) +LINESTRING Z EMPTY +LINESTRING Z M EMPTY +LINESTRING ZM (-117 33 2 3, -116 34 4 5) +LINESTRING ZM (0 0 1 4, 1 1 2 5, 2 2 3 6) +LINESTRING ZM EMPTY +LINESTRING(-117 33, -116 34) +LINESTRINGM EMPTY +LINESTRINGZ EMPTY +LINESTRINGZ(0 0 1, 1 1 1) +LINESTRINGZM EMPTY +MULTILINESTRING ((0 0, 1 1, 2 2), (3 3, 4 4, 5 5)) +MULTILINESTRING EMPTY +MULTILINESTRING M ((0 0 4, 1 1 5, 2 2 6), (3 3 7, 4 4 8, 5 5 9)) +MULTILINESTRING M EMPTY +MULTILINESTRING Z ((0 0 1, 1 1 2, 2 2 3), (3 3 4, 4 4 5, 5 5 6)) +MULTILINESTRING Z EMPTY +MULTILINESTRING Z M EMPTY +MULTILINESTRING ZM ((0 0 1 4, 1 1 2 5, 2 2 3 6), (3 3 4 7, 4 4 5 8, 5 5 6 9)) +MULTILINESTRING ZM EMPTY +MULTILINESTRINGM EMPTY +MULTILINESTRINGZ EMPTY +MULTILINESTRINGZM EMPTY +MULTIPOINT ((0 0), (1 1), (2 2)) +MULTIPOINT ((0 0), (1 2)) +MULTIPOINT (0 0, 1 2) +MULTIPOINT EMPTY +MULTIPOINT M ((0 0 3), (1 2 5)) +MULTIPOINT M ((0 0 4), (1 1 5), (2 2 6)) +MULTIPOINT M (0 0 3, 1 2 5) +MULTIPOINT M EMPTY +MULTIPOINT Z ((0 0 1), (1 1 2), (2 2 3)) +MULTIPOINT Z ((0 0 4), (1 2 4)) +MULTIPOINT Z (0 0 4, 1 2 4) +MULTIPOINT Z EMPTY +MULTIPOINT Z M EMPTY +MULTIPOINT ZM ((0 0 1 4), (1 1 2 5), (2 2 3 6)) +MULTIPOINT ZM ((0 0 4 3), (1 2 4 5)) +MULTIPOINT ZM (0 0 4 3, 1 2 4 5) +MULTIPOINT ZM EMPTY +MULTIPOINT((1 1), EMPTY) +MULTIPOINT(EMPTY, EMPTY) +MULTIPOINT(EMPTY, (1 1)) +MULTIPOINTM EMPTY +MULTIPOINTZ EMPTY +MULTIPOINTZM EMPTY +MULTIPOLYGON (((0 0, 0 3, 3 3, 3 0, 0 0)), ((1 1, 1 4, 4 4, 4 1, 1 1))) +MULTIPOLYGON (((10 10, 10 13, 13 13, 13 10, 10 10)), ((1 1, 1 4, 4 4, 4 1, 1 1), ( 2 2, 2 3, 3 3, 3 2, 2 2))) +MULTIPOLYGON EMPTY +MULTIPOLYGON M (((0 0 4, 0 3 5, 3 3 6, 3 0 7, 0 0 4)), ((1 1 9, 1 4 10, 4 4 11, 4 1 12, 1 1 9))) +MULTIPOLYGON M EMPTY +MULTIPOLYGON Z (((0 0 1, 0 3 2, 3 3 3, 3 0 4, 0 0 1)), ((1 1 5, 1 4 6, 4 4 7, 4 1 8, 1 1 5))) +MULTIPOLYGON Z EMPTY +MULTIPOLYGON Z M EMPTY +MULTIPOLYGON ZM (((0 0 1 4, 0 3 2 5, 3 3 3 6, 3 0 4 7, 0 0 1 4)), ((1 1 5 8, 1 4 6 9, 4 4 7 10, 4 1 8 11, 1 1 5 8))) +MULTIPOLYGON ZM EMPTY +MULTIPOLYGONM EMPTY +MULTIPOLYGONZ EMPTY +MULTIPOLYGONZM EMPTY +POINT (2 8) +POINT (2.0 4.0) +POINT EMPTY +POINT M EMPTY +POINT M(1 2 3) +POINT M (5.0 6.0 7.0) +POINT Z (1.0 2.0 3.0) +POINT Z EMPTY +POINT Z M EMPTY +POINT ZM EMPTY +POINTM EMPTY +POINTZ EMPTY +POINTZM EMPTY +POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0)) +POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0), (1 1, 3 1, 3 3, 1 3, 1 1)) +POLYGON EMPTY +POLYGON M ((0 0 4, 0 3 5, 3 3 6, 3 0 7, 0 0 4)) +POLYGON M EMPTY +POLYGON Z ((0 0 1, 0 3 2, 3 3 3, 3 0 4, 0 0 1)) +POLYGON Z ((0 0,0 10,10 10,10 0,0 0),(1 1 1,1 2 1,2 2 1,2 1 1,1 1 1)) +POLYGON Z EMPTY +POLYGON Z M EMPTY +POLYGON ZM ((0 0 1 4, 0 3 2 5, 3 3 3 6, 3 0 4 7, 0 0 1 4)) +POLYGON ZM EMPTY +POLYGON( EMPTY, (1 1,2 2,1 2,1 1)) +POLYGON((0 0, 0 1, 1 1, 1 0)) +POLYGONM EMPTY +POLYGONZ EMPTY +POLYGONZM EMPTY +TRIANGLE EMPTY +TRIANGLEM EMPTY +TRIANGLEZ EMPTY +TRIANGLEZM EMPTY +TRIANGLE M EMPTY +TRIANGLE Z EMPTY +TRIANGLE ZM EMPTY +TRIANGLE Z M EMPTY +TRIANGLE ((0 0, 5 5, 0 5, 0 0)) +TRIANGLE Z ((0 0 1, 5 5 5, 0 5 2, 0 0 1)) +TRIANGLE M ((0 0 1, 5 5 5, 0 5 2, 0 0 1)) +TRIANGLE ZM ((0 0 1 2, 5 5 5 3, 0 5 2 4, 0 0 1 2)) +TIN (((0 0 0, 0 1 0, 1 1 0, 0 0 0)), ((0.5 0.5 1, 0.5 1.5 1, 1.5 1.5 1, 0.5 0.5 1))) +TIN (((0 0, 0 1, 1 1, 0 0))) +TIN EMPTY +TIN M EMPTY +TIN M(((0 0 0, 0 1 0, 1 1 0, 0 0 0))) +TIN Z EMPTY +TIN Z M EMPTY +TIN Z(((0 0 0, 0 1 0, 1 1 0, 0 0 0))) +TIN ZM EMPTY +TINM EMPTY +TINZ EMPTY +TINZM EMPTY +POLYHEDRALSURFACE (((0 0, 0 1, 1 1, 1 0, 0 0))) +POLYHEDRALSURFACE Z (((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))) +POLYHEDRALSURFACE M (((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))) +POLYHEDRALSURFACE ZM (((0 0 0 1, 0 1 0 2, 1 1 0 3, 1 0 0 4, 0 0 0 1))) +POLYHEDRALSURFACE (((0 0, 0 1, 1 1, 1 0, 0 0)), ((1 1, 1 2, 2 2, 2 1, 1 1))) +POLYHEDRALSURFACE Z (((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((1 1 1, 1 2 1, 2 2 1, 2 1 1, 1 1 1))) +POLYHEDRALSURFACE M (((0 0 1, 0 1 2, 1 1 3, 1 0 4, 0 0 1)), ((1 1 5, 1 2 6, 2 2 7, 2 1 8, 1 1 5))) +POLYHEDRALSURFACE ZM (((0 0 0 1, 0 1 0 2, 1 1 0 3, 1 0 0 4, 0 0 0 1)), ((1 1 1 5, 1 2 1 6, 2 2 1 7, 2 1 1 8, 1 1 1 5))) +POLYHEDRALSURFACE EMPTY +POLYHEDRALSURFACEM EMPTY +POLYHEDRALSURFACEZ EMPTY +POLYHEDRALSURFACEZM EMPTY +POLYHEDRALSURFACE Z EMPTY +POLYHEDRALSURFACE M EMPTY +POLYHEDRALSURFACE ZM EMPTY +POLYHEDRALSURFACE Z M EMPTY diff --git a/test/unit/SFCGAL/io/WkbWriterTest.cpp b/test/unit/SFCGAL/io/WkbWriterTest.cpp new file mode 100644 index 00000000..1c2268cd --- /dev/null +++ b/test/unit/SFCGAL/io/WkbWriterTest.cpp @@ -0,0 +1,133 @@ +// Copyright (c) 2023-2023, Oslandia. +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +using namespace boost::unit_test; + +using namespace SFCGAL; +using namespace SFCGAL::io; + +#include "../../../test_config.h" + +BOOST_AUTO_TEST_SUITE(SFCGAL_io_WkbWriterTest) + +const std::vector allowedBeThyFail{ + "GEOMETRYCOLLECTION (POINT Z (1 2 3), LINESTRING (0 0, 1 1, 2 2), " + "POLYGON Z ((0 0 1, 0 3 2, 3 3 3, 3 0 4, 0 0 1)), MULTIPOINT M ((1 1 " + "4), (2 2 5)))", + "GEOMETRYCOLLECTION (POINT ZM (1 2 3 4), POINT EMPTY, POLYGON ((0 0, 0 " + "4, 4 4, 4 0, 0 0)), POLYGON ZM ((0 0 1 4, 0 3 2 5, 3 3 3 6, 3 0 4 7, " + "0 0 1 4)), POLYGON EMPTY)", + "POLYGON Z ((0 0,0 10,10 10,10 0,0 0),(1 1 1,1 2 1,2 2 1,2 1 1,1 1 " + "1))"}; +BOOST_AUTO_TEST_CASE(writeWkb) +{ + std::string inputData(SFCGAL_TEST_DIRECTORY); + inputData += "/data/WKT.txt"; + std::ifstream ifs(inputData.c_str()); + BOOST_REQUIRE(ifs.good()); + + std::string expectedData(SFCGAL_TEST_DIRECTORY); + expectedData += "/data/WKB_expected.txt"; + std::ifstream efs(expectedData.c_str()); + BOOST_REQUIRE(efs.good()); + + std::string inputWkt; + std::string expectedWkb; + while (std::getline(ifs, inputWkt)) { + std::unique_ptr g(io::readWkt(inputWkt)); + std::getline(efs, expectedWkb); + BOOST_CHECK_EQUAL(g->asWkb(), expectedWkb); + } +} + +BOOST_AUTO_TEST_CASE(readWkb) +{ + std::string inputData(SFCGAL_TEST_DIRECTORY); + inputData += "/data/WKT.txt"; + std::ifstream ifs(inputData.c_str()); + BOOST_REQUIRE(ifs.good()); + + std::string expectedData(SFCGAL_TEST_DIRECTORY); + expectedData += "/data/WKB_expected.txt"; + std::ifstream efs(expectedData.c_str()); + BOOST_REQUIRE(efs.good()); + + std::string inputWkt; + std::string expectedWkb; + while (std::getline(ifs, inputWkt)) { + std::getline(efs, expectedWkb); + std::unique_ptr g(io::readWkt(inputWkt)); + std::unique_ptr gWkb(io::readWkb(expectedWkb)); + if (std::find(allowedBeThyFail.begin(), allowedBeThyFail.end(), inputWkt) == + std::end(allowedBeThyFail)) { + BOOST_CHECK_EQUAL(g->asText(0), gWkb->asText(0)); + } + } +} + +BOOST_AUTO_TEST_CASE(PostgisEWkb) +{ + std::string inputData(SFCGAL_TEST_DIRECTORY); + inputData += "/data/EWKB_postgis.txt"; + std::ifstream ifs(inputData.c_str()); + BOOST_REQUIRE(ifs.good()); + + std::string expectedData(SFCGAL_TEST_DIRECTORY); + expectedData += "/data/WKT.txt"; + std::ifstream efs(expectedData.c_str()); + BOOST_REQUIRE(efs.good()); + + std::string inputWkb; + std::string expectedWkt; + auto i{0}; + while (std::getline(ifs, inputWkb)) { + std::getline(efs, expectedWkt); + std::unique_ptr gWkt(io::readWkt(expectedWkt)); + std::string ewkt = "SRID=3946;" + expectedWkt; + std::unique_ptr gEwkt(io::readEwkt(ewkt)); + if (!(expectedWkt.find("EMPTY") != std::string::npos) && + !inputWkb.empty()) { + BOOST_CHECK_EQUAL(gEwkt->asEWKB(), inputWkb); + } + + std::vector allowedBeThyFailFull = allowedBeThyFail; + allowedBeThyFailFull.emplace_back( + "GEOMETRYCOLLECTION (LINESTRING (0 0, 1 1), POLYGON EMPTY)"); + + allowedBeThyFailFull.emplace_back( + "GEOMETRYCOLLECTION (POINT (1 2), POINT EMPTY)"); + allowedBeThyFailFull.emplace_back("MULTIPOINT((1 1), EMPTY)"); + allowedBeThyFailFull.emplace_back("MULTIPOINT(EMPTY, EMPTY)"); + allowedBeThyFailFull.emplace_back("MULTIPOINT(EMPTY, (1 1))"); + if (std::find(allowedBeThyFailFull.begin(), allowedBeThyFailFull.end(), + expectedWkt) == std::end(allowedBeThyFailFull)) { + if (!inputWkb.empty()) { + std::unique_ptr gEwkbFile(io::readEwkb(inputWkb)); + BOOST_CHECK_EQUAL(gEwkbFile->geometry().asText(0), gWkt->asText(0)); + BOOST_CHECK_EQUAL(3946, gEwkbFile->SRID()); + } + } + } +} +BOOST_AUTO_TEST_SUITE_END()