[geos-commits] [SCM] GEOS branch master updated. 1d34d2c497786920f69521c77e50620f2efb34a6

git at osgeo.org git at osgeo.org
Thu Aug 13 12:57:12 PDT 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".

The branch, master has been updated
       via  1d34d2c497786920f69521c77e50620f2efb34a6 (commit)
      from  8a4f50edddd9740742562b3f81ea2f5880eaf093 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1d34d2c497786920f69521c77e50620f2efb34a6
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Thu Aug 13 12:28:14 2020 -0700

    Support reading WKB that includes M coordinates, but do not actually store the M (because we have nowhere to store it right now). References #460

diff --git a/include/geos/io/WKBReader.h b/include/geos/io/WKBReader.h
index 63e4128..33461ee 100644
--- a/include/geos/io/WKBReader.h
+++ b/include/geos/io/WKBReader.h
@@ -22,12 +22,12 @@
 
 #include <geos/export.h>
 
-#include <geos/geom/GeometryFactory.h>
 #include <geos/io/ByteOrderDataInStream.h> // for composition
 
 #include <iosfwd> // ostream, istream
 #include <memory>
-#include <vector>
+// #include <vector>
+#include <array>
 
 #define BAD_GEOM_TYPE_MSG "Bad geometry type encountered in"
 
@@ -40,7 +40,7 @@
 namespace geos {
 namespace geom {
 
-//class GeometryFactory;
+class GeometryFactory;
 class Coordinate;
 class Geometry;
 class GeometryCollection;
@@ -52,6 +52,7 @@ class MultiPoint;
 class MultiLineString;
 class MultiPolygon;
 class PrecisionModel;
+class CoordinateSequence;
 
 } // namespace geom
 } // namespace geos
@@ -80,7 +81,7 @@ class GEOS_DLL WKBReader {
 
 public:
 
-    WKBReader(geom::GeometryFactory const& f): factory(f) {}
+    WKBReader(geom::GeometryFactory const& f);
 
     /// Inizialize parser with default GeometryFactory.
     WKBReader();
@@ -119,10 +120,12 @@ private:
 
     // for now support the WKB standard only - may be generalized later
     unsigned int inputDimension;
+    bool hasZ;
+    bool hasM;
 
     ByteOrderDataInStream dis;
 
-    std::vector<double> ordValues;
+    std::array<double, 4> ordValues;
 
     std::unique_ptr<geom::Geometry> readGeometry();
 
diff --git a/src/io/WKBReader.cpp b/src/io/WKBReader.cpp
index f264f38..c38c367 100644
--- a/src/io/WKBReader.cpp
+++ b/src/io/WKBReader.cpp
@@ -46,10 +46,16 @@ using namespace geos::geom;
 namespace geos {
 namespace io { // geos.io
 
+WKBReader::WKBReader(geom::GeometryFactory const& f)
+    : factory(f)
+    , inputDimension(2)
+    , hasZ(false)
+    , hasM(false)
+    {}
+
 WKBReader::WKBReader()
-    :
-    factory(*(GeometryFactory::getDefaultInstance()))
-{}
+    : WKBReader(*(GeometryFactory::getDefaultInstance()))
+    {}
 
 ostream&
 WKBReader::printHEX(istream& is, ostream& os)
@@ -195,21 +201,25 @@ WKBReader::readGeometry()
     /* ISO type range 1000 is Z, 2000 is M, 3000 is ZM */
     int isoTypeRange = (typeInt & 0xffff) / 1000;
     int isoHasZ = (isoTypeRange == 1) || (isoTypeRange == 3);
-    //int isoHasM = (isoTypeRange == 2) || (isoTypeRange == 3);
+    int isoHasM = (isoTypeRange == 2) || (isoTypeRange == 3);
     /* SFSQL high bit flag for Z, next bit for M */
     int sfsqlHasZ = (typeInt & 0x80000000) != 0;
-    //int sfsqlHasM = (typeInt & 0x40000000) != 0;
+    int sfsqlHasM = (typeInt & 0x40000000) != 0;
 
 #if DEBUG_WKB_READER
     cout << "WKB geometryType: " << geometryType << endl;
 #endif
 
-    bool hasZ = sfsqlHasZ || isoHasZ;
-    if(hasZ) {
+    hasZ = sfsqlHasZ || isoHasZ;
+    hasM = sfsqlHasM || isoHasM;
+    if(hasZ && hasM) {
+        inputDimension = 4;
+    }
+    else if (hasZ || hasM) {
         inputDimension = 3;
     }
     else {
-        inputDimension = 2;    // doesn't handle M currently
+        inputDimension = 2;
     }
 
 #if DEBUG_WKB_READER
@@ -231,12 +241,6 @@ WKBReader::readGeometry()
         SRID = dis.readInt();    // read SRID
     }
 
-
-    // allocate space for ordValues
-    if(ordValues.size() < inputDimension) {
-        ordValues.resize(inputDimension);
-    }
-
     std::unique_ptr<Geometry> result;
 
     switch(geometryType) {
@@ -275,7 +279,7 @@ std::unique_ptr<Point>
 WKBReader::readPoint()
 {
     readCoordinate();
-    if(inputDimension == 3) {
+    if (hasZ) {
         return std::unique_ptr<Point>(factory.createPoint(Coordinate(ordValues[0], ordValues[1], ordValues[2])));
     }
     else {
@@ -377,7 +381,7 @@ WKBReader::readMultiPolygon()
         if(!dynamic_cast<Polygon*>(geoms[i].get())) {
             stringstream err;
             err << BAD_GEOM_TYPE_MSG << " Polygon";
-            throw  ParseException(err.str());
+            throw ParseException(err.str());
         }
     }
 
@@ -400,12 +404,12 @@ WKBReader::readGeometryCollection()
 std::unique_ptr<CoordinateSequence>
 WKBReader::readCoordinateSequence(int size)
 {
-    auto seq = factory.getCoordinateSequenceFactory()->create(size, inputDimension);
-    auto targetDim = seq->getDimension();
+    unsigned int targetDim = 2 + (hasZ ? 1 : 0);
+    auto seq = factory.getCoordinateSequenceFactory()->create(size, targetDim);
     if(targetDim > inputDimension) {
         targetDim = inputDimension;
     }
-    for(int i = 0; i < size; i++) {
+    for(unsigned int i = 0; i < size; i++) {
         readCoordinate();
         for(unsigned int j = 0; j < targetDim; j++) {
             seq->setOrdinate(i, j, ordValues[j]);
@@ -418,13 +422,17 @@ void
 WKBReader::readCoordinate()
 {
     const PrecisionModel& pm = *factory.getPrecisionModel();
-    for(unsigned int i = 0; i < inputDimension; ++i) {
-        if(i <= 1) {
+    for(std::size_t i = 0; i < inputDimension; ++i) {
+        if (i < 2) {
             ordValues[i] = pm.makePrecise(dis.readDouble());
         }
-        else {
+        else if (hasZ) {
             ordValues[i] = dis.readDouble();
         }
+        else {
+            // Read and throw away any extra (M) dimensions
+            dis.readDouble();
+        }
     }
 #if DEBUG_WKB_READER
     cout << "WKB coordinate: " << ordValues[0] << "," << ordValues[1] << endl;
diff --git a/tests/unit/capi/GEOSContainsTest.cpp b/tests/unit/capi/GEOSContainsTest.cpp
index d06ce2e..558e61f 100644
--- a/tests/unit/capi/GEOSContainsTest.cpp
+++ b/tests/unit/capi/GEOSContainsTest.cpp
@@ -6,6 +6,7 @@
 #include <geos_c.h>
 #include <geos/io/WKBReader.h>
 #include <geos/geom/PrecisionModel.h>
+#include <geos/geom/GeometryFactory.h>
 // std
 #include <cstdarg>
 #include <cstdio>
diff --git a/tests/unit/capi/GEOSPreparedGeometryTest.cpp b/tests/unit/capi/GEOSPreparedGeometryTest.cpp
index ca760b9..040d0d1 100644
--- a/tests/unit/capi/GEOSPreparedGeometryTest.cpp
+++ b/tests/unit/capi/GEOSPreparedGeometryTest.cpp
@@ -6,6 +6,7 @@
 #include <geos_c.h>
 #include <geos/io/WKBReader.h>
 #include <geos/geom/PrecisionModel.h>
+#include <geos/geom/GeometryFactory.h>
 // std
 #include <cstdarg>
 #include <cstdio>
diff --git a/tests/unit/io/WKBReaderTest.cpp b/tests/unit/io/WKBReaderTest.cpp
index c313252..82cd14d 100644
--- a/tests/unit/io/WKBReaderTest.cpp
+++ b/tests/unit/io/WKBReaderTest.cpp
@@ -33,6 +33,7 @@ struct test_wkbreader_data {
     geos::io::WKBReader wkbreader;
     geos::io::WKBWriter xdrwkbwriter;
     geos::io::WKBWriter ndrwkbwriter;
+    geos::io::WKBWriter ndr3dwkbwriter;
     geos::io::WKTReader wktreader;
 
     typedef std::unique_ptr<geos::geom::Geometry> GeomPtr;
@@ -46,10 +47,24 @@ struct test_wkbreader_data {
         xdrwkbwriter(2, geos::io::WKBConstants::wkbXDR),
         // 2D only, NDR (little endian)
         ndrwkbwriter(2, geos::io::WKBConstants::wkbNDR),
+        // 3D only, NDR (little endian)
+        ndr3dwkbwriter(3, geos::io::WKBConstants::wkbNDR),
         wktreader(gf.get())
     {}
 
     void
+    testInput(const std::string& hexwkb,
+              const std::string& expected)
+    {
+        std::stringstream hexin(hexwkb);
+        GeomPtr g(wkbreader.readHEX(hexin));
+        std::stringstream ndr_out;
+        ndr3dwkbwriter.writeHEX(*g, ndr_out);
+        ensure_equals("hex output",
+                      ndr_out.str(), expected.c_str());
+    }
+
+    void
     testInputNdr(const std::string& WKT,
                  const std::string& ndrWKB)
     {
@@ -457,5 +472,57 @@ void object::test<19>
 }
 
 
+// POINT M (1 2 3)
+template<>
+template<>
+void object::test<20>
+()
+{
+    testInput(
+        "01D1070000000000000000F03F00000000000000400000000000000840",
+        "0101000000000000000000F03F0000000000000040"
+    );
+
+}
+
+// POINT ZM (1 2 3 4)
+template<>
+template<>
+void object::test<21>
+()
+{
+    testInput(
+        "01B90B0000000000000000F03F000000000000004000000000000008400000000000001040",
+        "0101000080000000000000F03F00000000000000400000000000000840"
+    );
+
+}
+
+// LINESTRING M (1 2 3, 4 5 6)
+template<>
+template<>
+void object::test<22>
+()
+{
+    testInput(
+        "01D207000002000000000000000000F03F00000000000000400000000000000840000000000000104000000000000014400000000000001840",
+        "010200000002000000000000000000F03F000000000000004000000000000010400000000000001440"
+    );
+
+}
+
+// LINESTRING ZM (1 2 3 4, 5 6 7 8)
+template<>
+template<>
+void object::test<23>
+()
+{
+    testInput(
+        "01BA0B000002000000000000000000F03F000000000000004000000000000008400000000000001040000000000000144000000000000018400000000000001C400000000000002040",
+        "010200008002000000000000000000F03F00000000000000400000000000000840000000000000144000000000000018400000000000001C40"
+    );
+
+}
+
 } // namespace tut
 

-----------------------------------------------------------------------

Summary of changes:
 include/geos/io/WKBReader.h                  | 13 +++---
 src/io/WKBReader.cpp                         | 52 ++++++++++++---------
 tests/unit/capi/GEOSContainsTest.cpp         |  1 +
 tests/unit/capi/GEOSPreparedGeometryTest.cpp |  1 +
 tests/unit/io/WKBReaderTest.cpp              | 67 ++++++++++++++++++++++++++++
 5 files changed, 107 insertions(+), 27 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list