diff --git a/src/NetTopologySuite.IO.SqlServerBytes/Geometries/UnsupportedGeometry.cs b/src/NetTopologySuite.IO.SqlServerBytes/Geometries/UnsupportedGeometry.cs new file mode 100644 index 0000000..419a2c8 --- /dev/null +++ b/src/NetTopologySuite.IO.SqlServerBytes/Geometries/UnsupportedGeometry.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using NetTopologySuite.IO.Properties; +using NetTopologySuite.IO.Serialization; + +namespace NetTopologySuite.Geometries +{ + internal class UnsupportedGeometry : Geometry + { + private readonly OpenGisType _shapeType; + + public UnsupportedGeometry(OpenGisType shapeType, Geography geography) + : base(GeometryFactory.Default) + { + _shapeType = shapeType; + Geography = geography; + } + + public Geography Geography { get; } + + private NotSupportedException Unsupported() + => new NotSupportedException(string.Format(Resources.UnexpectedGeographyType, _shapeType)); + + #region Unsupported overrides + + public override double Area => throw Unsupported(); + public override Geometry Boundary => throw Unsupported(); + public override Dimension BoundaryDimension => throw Unsupported(); + public override Point Centroid => throw Unsupported(); + public override Coordinate Coordinate => throw Unsupported(); + public override Coordinate[] Coordinates => throw Unsupported(); + public override Dimension Dimension => throw Unsupported(); + public override string GeometryType => throw Unsupported(); + public override Point InteriorPoint => throw Unsupported(); + public override bool IsEmpty => throw Unsupported(); + public override bool IsRectangle => throw Unsupported(); + public override bool IsSimple => throw Unsupported(); + public override bool IsValid => throw Unsupported(); + public override double Length => throw Unsupported(); + public override int NumGeometries => throw Unsupported(); + public override int NumPoints => throw Unsupported(); + public override OgcGeometryType OgcGeometryType => throw Unsupported(); + + protected override SortIndexValue SortIndex => throw Unsupported(); + + public override void Apply(ICoordinateFilter filter) => throw Unsupported(); + public override void Apply(ICoordinateSequenceFilter filter) => throw Unsupported(); + public override void Apply(IGeometryComponentFilter filter) => throw Unsupported(); + public override void Apply(IGeometryFilter filter) => throw Unsupported(); + public override bool Contains(Geometry g) => throw Unsupported(); + public override Geometry ConvexHull() => throw Unsupported(); + public override bool Covers(Geometry g) => throw Unsupported(); + public override bool Crosses(Geometry g) => throw Unsupported(); + public override double Distance(Geometry g) => throw Unsupported(); + public override bool Equals(object o) => throw Unsupported(); + public override bool EqualsExact(Geometry other, double tolerance) => throw Unsupported(); + public override bool EqualsTopologically(Geometry g) => throw Unsupported(); + public override Geometry GetGeometryN(int n) => throw Unsupported(); + public override int GetHashCode() => throw Unsupported(); + public override double[] GetOrdinates(Ordinate ordinate) => throw Unsupported(); + public override bool Intersects(Geometry g) => throw Unsupported(); + public override bool IsWithinDistance(Geometry geom, double distance) => throw Unsupported(); + public override void Normalize() => throw Unsupported(); + public override bool Overlaps(Geometry g) => throw Unsupported(); + public override IntersectionMatrix Relate(Geometry g) => throw Unsupported(); + public override bool Relate(Geometry g, string intersectionPattern) => throw Unsupported(); + public override Geometry Reverse() => throw Unsupported(); + public override string ToString() => throw Unsupported(); + public override bool Touches(Geometry g) => throw Unsupported(); + + protected override int CompareToSameClass(object o) => throw Unsupported(); + protected override int CompareToSameClass(object o, IComparer comp) => throw Unsupported(); + protected override Envelope ComputeEnvelopeInternal() => throw Unsupported(); + protected override Geometry CopyInternal() => throw Unsupported(); + protected override bool IsEquivalentClass(Geometry other) => throw Unsupported(); + + #endregion + } +} diff --git a/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesReader.cs b/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesReader.cs index 478c6ef..7508633 100644 --- a/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesReader.cs +++ b/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesReader.cs @@ -238,6 +238,12 @@ private Geometry ToGeometry(Geography geography) geometries.Remove(shapeIndex); break; + case OpenGisType.CircularString: + case OpenGisType.CompoundCurve: + case OpenGisType.CurvePolygon: + case OpenGisType.FullGlobe: + return new UnsupportedGeometry(shape.Type, geography); + default: throw new ParseException(string.Format(Resources.UnexpectedGeographyType, shape.Type)); } diff --git a/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesWriter.cs b/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesWriter.cs index bb20c5c..0dc721c 100644 --- a/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesWriter.cs +++ b/src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesWriter.cs @@ -123,6 +123,10 @@ private Geography ToGeography(Geometry geometry) { return new Geography { SRID = -1 }; } + if (geometry is UnsupportedGeometry unsupportedGeometry) + { + return unsupportedGeometry.Geography; + } var geometries = new Queue<(Geometry, int)>(); geometries.Enqueue((geometry, -1)); diff --git a/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesReaderTest.cs b/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesReaderTest.cs index 421d809..fef7e97 100644 --- a/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesReaderTest.cs +++ b/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesReaderTest.cs @@ -2,8 +2,8 @@ using System.Globalization; using NetTopologySuite.Geometries; using NetTopologySuite.Geometries.Implementation; -using NetTopologySuite.IO.Properties; using Xunit; +using Point = NetTopologySuite.Geometries.Point; namespace NetTopologySuite.IO { @@ -161,40 +161,17 @@ public void HandleOrdinates_works() Assert.Equal("POINT (1 2)", new WKTWriter(4).Write(point)); } - [Fact] - public void Read_throws_when_circular_string() - { - var ex = Assert.Throws( - () => Read("0000000002040300000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000000001000000020000000001000000FFFFFFFF0000000008")); - - Assert.Equal(string.Format(Resources.UnexpectedGeographyType, "CircularString"), ex.Message); - } - - [Fact] - public void Read_throws_when_compound_curve() - { - var ex = Assert.Throws( - () => Read("0000000002040400000000000000000000000000000000000000000000000000F03F00000000000000000000000000000040000000000000F03F0000000000000840000000000000000001000000030000000001000000FFFFFFFF0000000009020000000203")); - - Assert.Equal(string.Format(Resources.UnexpectedGeographyType, "CompoundCurve"), ex.Message); - } - - [Fact] - public void Read_throws_when_curve_polygon() - { - var ex = Assert.Throws( - () => Read("000000000204050000000000000000000040000000000000F03F000000000000F03F00000000000000400000000000000000000000000000F03F000000000000F03F00000000000000000000000000000040000000000000F03F01000000020000000001000000FFFFFFFF000000000A")); - - Assert.Equal(string.Format(Resources.UnexpectedGeographyType, "CurvePolygon"), ex.Message); - } - - [Fact] - public void Read_throws_when_full_globe() + [Theory] + [InlineData("0000000002040300000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000000001000000020000000001000000FFFFFFFF0000000008")] + [InlineData("0000000002040400000000000000000000000000000000000000000000000000F03F00000000000000000000000000000040000000000000F03F0000000000000840000000000000000001000000030000000001000000FFFFFFFF0000000009020000000203")] + [InlineData("000000000204050000000000000000000040000000000000F03F000000000000F03F00000000000000400000000000000000000000000000F03F000000000000F03F00000000000000000000000000000040000000000000F03F01000000020000000001000000FFFFFFFF000000000A")] + [InlineData("E61000000224000000000000000001000000FFFFFFFFFFFFFFFF0B")] + public void Can_round_trip_unsupported_types(string bytes) { - var ex = Assert.Throws( - () => Read("E61000000224000000000000000001000000FFFFFFFFFFFFFFFF0B")); + var geometry = Read(bytes); - Assert.Equal(string.Format(Resources.UnexpectedGeographyType, "FullGlobe"), ex.Message); + Assert.IsType(geometry); + Assert.Equal(bytes, SqlServerBytesWriterTest.Write(geometry)); } private Geometry Read( diff --git a/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesWriterTest.cs b/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesWriterTest.cs index 8f6b670..8accf93 100644 --- a/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesWriterTest.cs +++ b/test/NetTopologySuite.IO.SqlServerBytes.Test/SqlServerBytesWriterTest.cs @@ -209,7 +209,7 @@ public void Types_still_unknown(string wkt) () => reader.Read(wkt)); } - private string Write( + public static string Write( Geometry geometry, Ordinates handleOrdinates = Ordinates.XYZM, bool isGeography = false)