From ce679719e09152713b06361ac97bcf582eb1b34e Mon Sep 17 00:00:00 2001 From: Felix Obermaier Date: Thu, 31 Oct 2024 09:50:04 +0100 Subject: [PATCH] Don't write extent in header for single point and empty geometries refers to #11 --- .../GeoPackageGeoWriter.cs | 46 ++++++++++--------- .../Issue11.cs | 39 ++++++++++++++++ ...NetTopologySuite.IO.SpatiaLite.Test.csproj | 2 +- 3 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 test/NetTopologySuite.IO.SpatiaLite.Test/Issue11.cs diff --git a/src/NetTopologySuite.IO.GeoPackage/GeoPackageGeoWriter.cs b/src/NetTopologySuite.IO.GeoPackage/GeoPackageGeoWriter.cs index 949c7e6..b13919d 100644 --- a/src/NetTopologySuite.IO.GeoPackage/GeoPackageGeoWriter.cs +++ b/src/NetTopologySuite.IO.GeoPackage/GeoPackageGeoWriter.cs @@ -68,25 +68,9 @@ public void Write(Geometry geom, Stream stream) using (var writer = new BinaryWriter(stream)) { int byteOrder = (int)ByteOrder.LittleEndian; - int ordinates = 0; - switch (HandleOrdinates) - { - case Ordinates.None: - ordinates = 0; - break; - case Ordinates.XY: - ordinates = 1; - break; - case Ordinates.XYZ: - ordinates = 2; - break; - case Ordinates.XYM: - ordinates = 3; - break; - case Ordinates.XYZM: - ordinates = 4; - break; - } + + int ordinates = GetExtentOrdinates(geom); + int isEmpty = geom.IsEmpty ? 1 : 0; byte flags = (byte)(byteOrder + (ordinates << 1) + (isEmpty << 4)); var header = new GeoPackageBinaryHeader @@ -117,12 +101,32 @@ public void Write(Geometry geom, Stream stream) } // NOTE: GeoPackage handles SRID in its own header. It would be invalid here. - const bool dontHandleSRID = false; - var wkbWriter = new WKBWriter(ByteOrder.LittleEndian, dontHandleSRID, emitZ, emitM); + const bool handleSRID = false; + var wkbWriter = new WKBWriter(ByteOrder.LittleEndian, handleSRID, emitZ, emitM); wkbWriter.Write(geom, stream); } } + private int GetExtentOrdinates(Geometry geom) + { + if (geom.IsEmpty || geom.OgcGeometryType == OgcGeometryType.Point) + return 0; + + switch (HandleOrdinates) + { + case Ordinates.XY: + return 1; + case Ordinates.XYZ: + return 2; + case Ordinates.XYM: + return 3; + case Ordinates.XYZM: + return 4; + } + + return 0; + } + /// /// Serializes a given to a new byte array. /// diff --git a/test/NetTopologySuite.IO.SpatiaLite.Test/Issue11.cs b/test/NetTopologySuite.IO.SpatiaLite.Test/Issue11.cs new file mode 100644 index 0000000..84a6629 --- /dev/null +++ b/test/NetTopologySuite.IO.SpatiaLite.Test/Issue11.cs @@ -0,0 +1,39 @@ +using NetTopologySuite; +using NetTopologySuite.Geometries; +using NetTopologySuite.IO; +using NUnit.Framework; + +namespace NetTopologySuite.IO.SpatiaLite.Test; + +class Issue11 +{ + [TestCase("POINT EMPTY", 17)] + [TestCase("POINT(10 10)", 1)] + [TestCase("POINT Z(10 10 1)", 1)] + [TestCase("POINT M(10 10 2)", 1)] + [TestCase("POINT ZM(10 10 1 2)", 1)] + [TestCase("POINT(10 10)", 1)] + [TestCase("LINESTRING EMPTY", 17)] + [TestCase("LINESTRING(10 10, 10 20)", 3)] + [TestCase("LINESTRING Z(10 10 1, 10 20 1)", 3)] + [TestCase("LINESTRING M(10 10 2, 10 20 2)", 3)] + [TestCase("LINESTRING ZM(10 10 1 2, 10 20 1 2)", 3)] + public void TestHeaderFlags(string wkt, byte expectedFlags) + { + var factory = NtsGeometryServices.Instance.CreateGeometryFactory(); + var wktReader = new WKTReader() { IsOldNtsCoordinateSyntaxAllowed = false }; + var geom = wktReader.Read(wkt); + var writer = new GeoPackageGeoWriter + { + HandleOrdinates = Ordinates.None + }; + byte[] s = writer.Write(geom); + + Assert.That(s[3], Is.EqualTo(expectedFlags)); + + var reader = new GeoPackageGeoReader(factory.CoordinateSequenceFactory, factory.PrecisionModel); + var dgeom = reader.Read(s); + Assert.That(dgeom, Is.EqualTo(geom)); + } + +} \ No newline at end of file diff --git a/test/NetTopologySuite.IO.SpatiaLite.Test/NetTopologySuite.IO.SpatiaLite.Test.csproj b/test/NetTopologySuite.IO.SpatiaLite.Test/NetTopologySuite.IO.SpatiaLite.Test.csproj index 26f5f80..fdce8fd 100644 --- a/test/NetTopologySuite.IO.SpatiaLite.Test/NetTopologySuite.IO.SpatiaLite.Test.csproj +++ b/test/NetTopologySuite.IO.SpatiaLite.Test/NetTopologySuite.IO.SpatiaLite.Test.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net8