[geos-commits] [SCM] GEOS branch main updated. 76d0e8f344efbad4b41bafced76f3f8e48573ccb

git at osgeo.org git at osgeo.org
Tue Jun 11 06:07:42 PDT 2024


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, main has been updated
       via  76d0e8f344efbad4b41bafced76f3f8e48573ccb (commit)
      from  d0d3d5a0bf9c5a3f3bcb4da64ae53fef0f7d64e2 (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 76d0e8f344efbad4b41bafced76f3f8e48573ccb
Author: Dan Baston <dbaston at gmail.com>
Date:   Tue Jun 11 09:07:13 2024 -0400

    WKBWriter: Support curved geometry types (#1104)

diff --git a/include/geos/io/WKBConstants.h b/include/geos/io/WKBConstants.h
index 51d9615f4..438574841 100644
--- a/include/geos/io/WKBConstants.h
+++ b/include/geos/io/WKBConstants.h
@@ -37,7 +37,12 @@ namespace WKBConstants {
         wkbMultiPoint = 4,
         wkbMultiLineString = 5,
         wkbMultiPolygon = 6,
-        wkbGeometryCollection = 7
+        wkbGeometryCollection = 7,
+        wkbCircularString = 8,
+        wkbCompoundCurve = 9,
+        wkbCurvePolygon = 10,
+        wkbMultiCurve = 11,
+        wkbMultiSurface = 12,
     };
 
     enum wkbFlavour {
diff --git a/include/geos/io/WKBWriter.h b/include/geos/io/WKBWriter.h
index 0910f52f5..90b2fbc67 100644
--- a/include/geos/io/WKBWriter.h
+++ b/include/geos/io/WKBWriter.h
@@ -33,6 +33,8 @@ namespace geos {
 namespace geom {
 
 class CoordinateSequence;
+class CompoundCurve;
+class CurvePolygon;
 class Geometry;
 class GeometryCollection;
 class Point;
@@ -43,6 +45,7 @@ class MultiPoint;
 class MultiLineString;
 class MultiPolygon;
 class PrecisionModel;
+class SimpleCurve;
 
 } // namespace geom
 } // namespace geos
@@ -194,6 +197,8 @@ public:
     void writeHEX(const geom::Geometry& g, std::ostream& os);
     // throws IOException, ParseException
 
+    static int getWkbType(const geom::Geometry&);
+
 private:
 
     // 2, 3, or 4
@@ -215,13 +220,17 @@ private:
     void writePointEmpty(const geom::Point& p);
     // throws IOException
 
-    void writeLineString(const geom::LineString& ls);
+    void writeSimpleCurve(const geom::SimpleCurve& ls);
     // throws IOException
 
+    void writeCompoundCurve(const geom::CompoundCurve& curve);
+
     void writePolygon(const geom::Polygon& p);
     // throws IOException
 
-    void writeGeometryCollection(const geom::GeometryCollection& c, int wkbtype);
+    void writeCurvePolygon(const geom::CurvePolygon& p);
+
+    void writeGeometryCollection(const geom::GeometryCollection& gc);
     // throws IOException, ParseException
 
     void writeCoordinateSequence(const geom::CoordinateSequence& cs, bool sized);
diff --git a/src/io/WKBWriter.cpp b/src/io/WKBWriter.cpp
index 0e622b0d4..f7c83d38d 100644
--- a/src/io/WKBWriter.cpp
+++ b/src/io/WKBWriter.cpp
@@ -22,6 +22,8 @@
 #include <geos/io/CheckOrdinatesFilter.h>
 #include <geos/util/IllegalArgumentException.h>
 #include <geos/geom/Coordinate.h>
+#include <geos/geom/CompoundCurve.h>
+#include <geos/geom/CurvePolygon.h>
 #include <geos/geom/Point.h>
 #include <geos/geom/LinearRing.h>
 #include <geos/geom/LineString.h>
@@ -99,8 +101,6 @@ WKBWriter::writeHEX(const Geometry& g, std::ostream& os)
 void
 WKBWriter::write(const Geometry& g, std::ostream& os)
 {
-    util::ensureNoCurvedComponents(g);
-
     OrdinateSet inputOrdinates = OrdinateSet::createXY();
     inputOrdinates.setM(g.hasM());
     inputOrdinates.setZ(g.hasZ());
@@ -108,36 +108,21 @@ WKBWriter::write(const Geometry& g, std::ostream& os)
 
     outStream = &os;
 
-    if (const Point* x = dynamic_cast<const Point*>(&g)) {
-        return writePoint(*x);
+    switch(g.getGeometryTypeId()) {
+        case GEOS_POINT: writePoint(static_cast<const Point&>(g)); break;
+        case GEOS_LINESTRING:
+        case GEOS_LINEARRING:
+        case GEOS_CIRCULARSTRING: writeSimpleCurve(static_cast<const SimpleCurve&>(g)); break;
+        case GEOS_COMPOUNDCURVE: writeCompoundCurve(static_cast<const CompoundCurve&>(g)); break;
+        case GEOS_POLYGON: writePolygon(static_cast<const Polygon&>(g)); break;
+        case GEOS_CURVEPOLYGON: writeCurvePolygon(static_cast<const CurvePolygon&>(g)); break;
+        case GEOS_MULTIPOINT:
+        case GEOS_MULTILINESTRING:
+        case GEOS_MULTIPOLYGON:
+        case GEOS_MULTICURVE:
+        case GEOS_MULTISURFACE:
+        case GEOS_GEOMETRYCOLLECTION: writeGeometryCollection(static_cast<const GeometryCollection&>(g)); break;
     }
-
-    if (const LineString* x = dynamic_cast<const LineString*>(&g)) {
-        return writeLineString(*x);
-    }
-
-    if (const Polygon* x = dynamic_cast<const Polygon*>(&g)) {
-        return writePolygon(*x);
-    }
-
-    if (const MultiPoint* x = dynamic_cast<const MultiPoint*>(&g)) {
-        return writeGeometryCollection(*x, WKBConstants::wkbMultiPoint);
-    }
-
-    if (const MultiLineString* x = dynamic_cast<const MultiLineString*>(&g)) {
-        return writeGeometryCollection(*x, WKBConstants::wkbMultiLineString);
-    }
-
-    if (const MultiPolygon* x = dynamic_cast<const MultiPolygon*>(&g)) {
-        return writeGeometryCollection(*x, WKBConstants::wkbMultiPolygon);
-    }
-
-    if (const GeometryCollection* x =
-                dynamic_cast<const GeometryCollection*>(&g)) {
-        return writeGeometryCollection(*x, WKBConstants::wkbGeometryCollection);
-    }
-
-    assert(0); // Unknown Geometry type
 }
 
 void
@@ -172,11 +157,11 @@ WKBWriter::writePoint(const Point& g)
 }
 
 void
-WKBWriter::writeLineString(const LineString& g)
+WKBWriter::writeSimpleCurve(const SimpleCurve& g)
 {
     writeByteOrder();
 
-    writeGeometryType(WKBConstants::wkbLineString, g.getSRID());
+    writeGeometryType(getWkbType(g), g.getSRID());
     writeSRID(g.getSRID());
 
     const CoordinateSequence* cs = g.getCoordinatesRO();
@@ -184,12 +169,33 @@ WKBWriter::writeLineString(const LineString& g)
     writeCoordinateSequence(*cs, true);
 }
 
+void
+WKBWriter::writeCompoundCurve(const CompoundCurve& g)
+{
+    writeByteOrder();
+
+    writeGeometryType(getWkbType(g), g.getSRID());
+    writeSRID(g.getSRID());
+
+    writeInt(static_cast<int>(g.getNumCurves()));
+
+    auto orig_includeSRID = includeSRID;
+    includeSRID = false;
+
+    for (std::size_t i = 0; i < g.getNumCurves(); i++) {
+        const SimpleCurve& section = *g.getCurveN(i);
+        writeSimpleCurve(section);
+    }
+
+    includeSRID = orig_includeSRID;
+}
+
 void
 WKBWriter::writePolygon(const Polygon& g)
 {
     writeByteOrder();
 
-    writeGeometryType(WKBConstants::wkbPolygon, g.getSRID());
+    writeGeometryType(getWkbType(g), g.getSRID());
     writeSRID(g.getSRID());
 
     if (g.isEmpty()) {
@@ -219,12 +225,42 @@ WKBWriter::writePolygon(const Polygon& g)
 }
 
 void
-WKBWriter::writeGeometryCollection(const GeometryCollection& g,
-                                   int wkbtype)
+WKBWriter::writeCurvePolygon(const CurvePolygon& g)
+{
+    // Why not combine this with writePolygon?
+    // A CurvePolygon differs from a Polygon in that its rings
+    // can one of three different types. Therefore, the type
+    // information is written for each ring, unlike a Polygon.
+
+    writeByteOrder();
+
+    writeGeometryType(getWkbType(g), g.getSRID());
+
+    writeSRID(g.getSRID());
+
+    if (g.isEmpty()) {
+        writeInt(0);
+        return;
+    }
+
+    std::size_t nholes = g.getNumInteriorRing();
+    writeInt(static_cast<int>(nholes + 1));
+
+    const Curve* ring = g.getExteriorRing();
+    write(*ring, *outStream);
+
+    for(std::size_t i = 0; i < nholes; i++) {
+        ring = g.getInteriorRingN(i);
+        write(*ring, *outStream);
+    }
+}
+
+void
+WKBWriter::writeGeometryCollection(const GeometryCollection& g)
 {
     writeByteOrder();
 
-    writeGeometryType(wkbtype, g.getSRID());
+    writeGeometryType(getWkbType(g), g.getSRID());
     writeSRID(g.getSRID());
 
     auto ngeoms = g.getNumGeometries();
@@ -381,6 +417,28 @@ WKBWriter::getOutputOrdinates(OrdinateSet ordinates)
     return newOrdinates;
 }
 
+int
+WKBWriter::getWkbType(const Geometry& g) {
+    switch(g.getGeometryTypeId()) {
+        case GEOS_POINT: return WKBConstants::wkbPoint;
+        case GEOS_LINESTRING:
+        case GEOS_LINEARRING: return WKBConstants::wkbLineString;
+        case GEOS_CIRCULARSTRING: return WKBConstants::wkbCircularString;
+        case GEOS_COMPOUNDCURVE: return WKBConstants::wkbCompoundCurve;
+        case GEOS_POLYGON: return WKBConstants::wkbPolygon;
+        case GEOS_CURVEPOLYGON: return WKBConstants::wkbCurvePolygon;
+        case GEOS_MULTIPOINT: return WKBConstants::wkbMultiPoint;
+        case GEOS_MULTILINESTRING: return WKBConstants::wkbMultiLineString;
+        case GEOS_MULTICURVE: return WKBConstants::wkbMultiCurve;
+        case GEOS_MULTIPOLYGON: return WKBConstants::wkbMultiPolygon;
+        case GEOS_MULTISURFACE: return WKBConstants::wkbMultiSurface;
+        case GEOS_GEOMETRYCOLLECTION: return WKBConstants::wkbGeometryCollection;
+    }
+
+    // Avoid -Wreturn-type warning
+    throw util::IllegalArgumentException("Invalid geometry type.");
+}
+
 
 } // namespace geos.io
 } // namespace geos
diff --git a/tests/unit/capi/GEOSWKBWriterTest.cpp b/tests/unit/capi/GEOSWKBWriterTest.cpp
index 1bb95c808..2f3e041d6 100644
--- a/tests/unit/capi/GEOSWKBWriterTest.cpp
+++ b/tests/unit/capi/GEOSWKBWriterTest.cpp
@@ -186,18 +186,5 @@ void object::test<9>()
     ensure_equals(hexstr, "010100008000000000000008400000000000002040000000000000F03F");
 }
 
-template<>
-template<>
-void object::test<10>
-()
-{
-    input_ = fromWKT("CIRCULARSTRING (0 0, 1 1, 2 0)");
-    ensure(input_);
-
-    std::size_t hex_size = 0;
-    buf_ =  GEOSWKBWriter_writeHEX(wkbwriter_, input_, &hex_size);
-    ensure("curved geometry not supported", buf_ == nullptr);
-}
-
 } // namespace tut
 
diff --git a/tests/unit/io/WKBWriterTest.cpp b/tests/unit/io/WKBWriterTest.cpp
index eb4cf3102..ff31b7f0e 100644
--- a/tests/unit/io/WKBWriterTest.cpp
+++ b/tests/unit/io/WKBWriterTest.cpp
@@ -45,6 +45,22 @@ struct test_wkbwriter_data {
         wkbreader(*gf)
     {}
 
+    void checkHexOutput(const std::string& wkt, const std::string& hex) {
+        std::stringstream out;
+        auto geom = wktreader.read(wkt);
+        wkbwriter.writeHEX(*geom, out);
+        ensure_equals(wkt, out.str(), hex );
+    }
+
+    void checkHexOutputWithSRID(const std::string& wkt, int srid, const std::string& hex) {
+        std::stringstream out;
+        auto geom = wktreader.read(wkt);
+        geom->setSRID(srid);
+        wkbwriter.setIncludeSRID(true);
+        wkbwriter.writeHEX(*geom, out);
+        ensure_equals(wkt, out.str(), hex );
+    }
+
 };
 
 typedef test_group<test_wkbwriter_data> group;
@@ -375,5 +391,91 @@ void object::test<12>
                   "010200004002000000000000000000F03F00000000000000400000000000000840000000000000104000000000000014400000000000001840");
 }
 
+// CircularString
+template<>
+template<>
+void object::test<13>
+()
+{
+    checkHexOutput("CIRCULARSTRING EMPTY",
+                   "010800000000000000");
+
+    checkHexOutput("CIRCULARSTRING (1 3, 2 4, 3 1)",
+                   "010800000003000000000000000000F03F0000000000000840000000000000004000000000000010400000000000000840000000000000F03F");
+}
+
+// CompoundCurve
+template<>
+template<>
+void object::test<14>
+()
+{
+    checkHexOutput("COMPOUNDCURVE EMPTY",
+                   "010900000000000000");
+
+    checkHexOutput("COMPOUNDCURVE (CIRCULARSTRING (1 3, 2 4, 3 1), (3 1, 0 0))",
+                   "010900000002000000010800000003000000000000000000F03F0000000000000840000000000000004000000000000010400000000000000840000000000000F03F0102000000020000000000000000000840000000000000F03F00000000000000000000000000000000");
+}
+
+// CurvePolygon
+template<>
+template<>
+void object::test<15>
+()
+{
+    checkHexOutput("CURVEPOLYGON EMPTY",
+                   "010A00000000000000");
+
+    checkHexOutput("CURVEPOLYGON( COMPOUNDCURVE( CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3), (4 3, 4 5, 1 4, 0 0)), CIRCULARSTRING(1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1) )",
+                   "010A0000000200000001090000000200000001080000000500000000000000000000000000000000000000000000000000004000000000000000000000000000000040000000000000F03F00000000000000400000000000000840000000000000104000000000000008400102000000040000000000000000001040000000000000084000000000000010400000000000001440000000000000F03F000000000000104000000000000000000000000000000000010800000005000000333333333333FB3F000000000000F03F666666666666F63F9A9999999999D93F9A9999999999F93F9A9999999999D93F9A9999999999F93F000000000000E03F333333333333FB3F000000000000F03F");
+}
+
+// MultiCurve
+template<>
+template<>
+void object::test<16>
+()
+{
+    checkHexOutput("MULTICURVE EMPTY",
+                   "010B00000000000000");
+
+    checkHexOutput("MULTICURVE( (0 0, 5 5), COMPOUNDCURVE( (-1 -1, 0 0), CIRCULARSTRING (0 0, 1 1, 2 0)), CIRCULARSTRING(4 0, 4 4, 8 4))",
+                   "010B000000030000000102000000020000000000000000000000000000000000000000000000000014400000000000001440010900000002000000010200000002000000000000000000F0BF000000000000F0BF0000000000000000000000000000000001080000000300000000000000000000000000000000000000000000000000F03F000000000000F03F00000000000000400000000000000000010800000003000000000000000000104000000000000000000000000000001040000000000000104000000000000020400000000000001040" );
+}
+
+// MultiSurface
+template<>
+template<>
+void object::test<17>
+()
+{
+    checkHexOutput("MULTISURFACE EMPTY",
+                   "010C00000000000000");
+
+    checkHexOutput("MULTISURFACE( CURVEPOLYGON( CIRCULARSTRING( 0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 3 3, 3 1, 1 1)), POLYGON ((10 10, 14 12, 11 10, 10 10), (11 11, 11.5 11, 11 11.5, 11 11)))",
+                   "010C00000002000000010A000000020000000108000000050000000000000000000000000000000000000000000000000010400000000000000000000000000000104000000000000010400000000000000000000000000000104000000000000000000000000000000000010200000004000000000000000000F03F000000000000F03F000000000000084000000000000008400000000000000840000000000000F03F000000000000F03F000000000000F03F01030000000200000004000000000000000000244000000000000024400000000000002C40000000000000284000000000000026400000000000002440000000000000244000000000000024400400000000000000000026400000000000002640000000000000274000000000000026400000000000002640000000000000274000000000000026400000000000002640");
+}
+
+// CompoundCurve with SRID
+template<>
+template<>
+void object::test<18>
+()
+{
+    checkHexOutputWithSRID("COMPOUNDCURVE (CIRCULARSTRING (1 3, 2 4, 3 1), (3 1, 0 0))", 5646,
+                  "01090000200E16000002000000010800000003000000000000000000F03F0000000000000840000000000000004000000000000010400000000000000840000000000000F03F0102000000020000000000000000000840000000000000F03F00000000000000000000000000000000");
+}
+
+// CurvePolygon with SRID
+template<>
+template<>
+void object::test<19>
+()
+{
+    checkHexOutputWithSRID("CURVEPOLYGON( COMPOUNDCURVE( CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3), (4 3, 4 5, 1 4, 0 0)), CIRCULARSTRING(1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1) )", 5646,
+                           "010A0000200E1600000200000001090000000200000001080000000500000000000000000000000000000000000000000000000000004000000000000000000000000000000040000000000000F03F00000000000000400000000000000840000000000000104000000000000008400102000000040000000000000000001040000000000000084000000000000010400000000000001440000000000000F03F000000000000104000000000000000000000000000000000010800000005000000333333333333FB3F000000000000F03F666666666666F63F9A9999999999D93F9A9999999999F93F9A9999999999D93F9A9999999999F93F000000000000E03F333333333333FB3F000000000000F03F");
+}
+
+
 } // namespace tut
 

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

Summary of changes:
 include/geos/io/WKBConstants.h        |   7 +-
 include/geos/io/WKBWriter.h           |  13 +++-
 src/io/WKBWriter.cpp                  | 132 ++++++++++++++++++++++++----------
 tests/unit/capi/GEOSWKBWriterTest.cpp |  13 ----
 tests/unit/io/WKBWriterTest.cpp       | 102 ++++++++++++++++++++++++++
 5 files changed, 214 insertions(+), 53 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list