Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Integrate with NetTopologySuite.Curved #20

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "NetTopologySuite.Curved"]
path = NetTopologySuite.Curved
url = https://github.com/NetTopologySuite/NetTopologySuite.Curved.git
1 change: 1 addition & 0 deletions NetTopologySuite.Curved
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NetTopologySuite" Version="[2.0.0, 3.0.0-A)" />
<ProjectReference Include="..\..\NetTopologySuite.Curved\src\NetTopologySuite.Curved\NetTopologySuite.Curved.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
14 changes: 13 additions & 1 deletion src/NetTopologySuite.IO.SqlServerBytes/SqlServerBytesReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ private Geometry ToGeometry(Geography geography)
bool handleZ = _handleOrdinates.HasFlag(Ordinates.Z) && geography.ZValues.Count > 0;
bool handleM = _handleOrdinates.HasFlag(Ordinates.M) && geography.MValues.Count > 0;

var factory = _services.CreateGeometryFactory(geography.SRID);
// TODO: Cache factories by SRID?
// TODO: Shouldn't this accept _services?
// TODO: Is arcSegmentLength the same as SQL Server's tolerance? Is this a good default?
var factory = new CurvedGeometryFactory(_services.DefaultPrecisionModel, geography.SRID, _services.DefaultCoordinateSequenceFactory, arcSegmentLength: 0.001);
var geometries = new Dictionary<int, Stack<Geometry>>();
int lastFigureIndex = geography.Figures.Count - 1;
int lastPointIndex = geography.Points.Count - 1;
Expand All @@ -144,6 +147,7 @@ private Geometry ToGeometry(Geography geography)
for (int figureIndex = lastFigureIndex; figureIndex >= shape.FigureOffset; figureIndex--)
{
var figure = geography.Figures[figureIndex];
// TODO: Handle Segments when FigureAttribute = Curve
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int pointCount = figure.PointOffset != -1
? lastPointIndex + 1 - figure.PointOffset
: 0;
Expand Down Expand Up @@ -238,6 +242,14 @@ private Geometry ToGeometry(Geography geography)
geometries.Remove(shapeIndex);
break;

case OpenGisType.CircularString:
// TODO: Assert it's an Arc?
geometry = factory.CreateCircularString(figures.SingleOrDefault());
Debug.Assert(!geometries.ContainsKey(shapeIndex));
break;

// TODO: Handle CompoundCurve & CurvePolygon

default:
throw new ParseException(string.Format(Resources.UnexpectedGeographyType, shape.Type));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ private Geography ToGeography(Geometry geometry)
}
break;

// TODO: Handle CircularString, CompoundCurve & CurvePolygon

default:
throw new InvalidOperationException(
string.Format(Resources.UnexpectedGeometryType, geometry.GetType()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ public class SqlServerBytesReaderTest
[InlineData(
"MULTIPOLYGON (((0 0, 0 1, 1 1, 0 0)))",
"00000000010404000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000001000000020000000002000000FFFFFFFF0000000006000000000000000003")]
[InlineData(
"CIRCULARSTRING (0 0, 1 1, 2 0)",
"0000000002040300000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000000001000000020000000001000000FFFFFFFF0000000008")]
// TODO: Test CompoundCurve with consecutive lines/arcs
[InlineData(
"COMPOUNDCURVE ((0 0, 1 0), CIRCULARSTRING (1 0, 2 1, 3 0))",
"0000000002040400000000000000000000000000000000000000000000000000F03F00000000000000000000000000000040000000000000F03F0000000000000840000000000000000001000000030000000001000000FFFFFFFF0000000009020000000203")]
// TODO: Test CurvePolygon with interior rings
[InlineData(
"CURVEPOLYGON (CIRCULARSTRING (2 1, 1 2, 0 1, 1 0, 2 1))",
"000000000204050000000000000000000040000000000000F03F000000000000F03F00000000000000400000000000000000000000000000F03F000000000000F03F00000000000000000000000000000040000000000000F03F01000000020000000001000000FFFFFFFF000000000A")]
public void Read_works(string expected, string bytes)
{
Assert.Equal(expected, Read(bytes).AsText());
Expand Down Expand Up @@ -161,33 +172,6 @@ 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<ParseException>(
() => Read("0000000002040300000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000000001000000020000000001000000FFFFFFFF0000000008"));

Assert.Equal(string.Format(Resources.UnexpectedGeographyType, "CircularString"), ex.Message);
}

[Fact]
public void Read_throws_when_compound_curve()
{
var ex = Assert.Throws<ParseException>(
() => Read("0000000002040400000000000000000000000000000000000000000000000000F03F00000000000000000000000000000040000000000000F03F0000000000000840000000000000000001000000030000000001000000FFFFFFFF0000000009020000000203"));

Assert.Equal(string.Format(Resources.UnexpectedGeographyType, "CompoundCurve"), ex.Message);
}

[Fact]
public void Read_throws_when_curve_polygon()
{
var ex = Assert.Throws<ParseException>(
() => Read("000000000204050000000000000000000040000000000000F03F000000000000F03F00000000000000400000000000000000000000000000F03F000000000000F03F00000000000000000000000000000040000000000000F03F01000000020000000001000000FFFFFFFF000000000A"));

Assert.Equal(string.Format(Resources.UnexpectedGeographyType, "CurvePolygon"), ex.Message);
}

[Fact]
public void Read_throws_when_full_globe()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,18 @@ public class SqlServerBytesWriterTest
[InlineData(
"MULTIPOLYGON (((0 0, 0 1, 1 1, 0 0)))",
"00000000010404000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000001000000020000000002000000FFFFFFFF0000000006000000000000000003")]
[InlineData(
"CIRCULARSTRING (0 0, 1 1, 2 0)",
"0000000002040300000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000000001000000020000000001000000FFFFFFFF0000000008")]
[InlineData(
"COMPOUNDCURVE ((0 0, 1 0), CIRCULARSTRING (1 0, 2 1, 3 0))",
"0000000002040400000000000000000000000000000000000000000000000000F03F00000000000000000000000000000040000000000000F03F0000000000000840000000000000000001000000030000000001000000FFFFFFFF0000000009020000000203")]
[InlineData(
"CURVEPOLYGON (CIRCULARSTRING (2 1, 1 2, 0 1, 1 0, 2 1))",
"000000000204050000000000000000000040000000000000F03F000000000000F03F00000000000000400000000000000000000000000000F03F000000000000F03F00000000000000000000000000000040000000000000F03F01000000020000000001000000FFFFFFFF000000000A")]
public void Write_works(string wkt, string expected)
{
var geometry = new WKTReader().Read(wkt);
var geometry = new WKTReaderEx().Read(wkt);

Assert.Equal(expected, Write(geometry));
}
Expand All @@ -89,7 +98,7 @@ public void Write_works(string wkt, string expected)
[InlineData("POLYGON EMPTY", "E61000000104000000000000000001000000FFFFFFFFFFFFFFFF03")]
public void Write_works_when_IsGeography(string wkt, string expectedHex)
{
var geometry = new WKTReader().Read(wkt);
var geometry = new WKTReaderEx().Read(wkt);
geometry.SRID = 4326;

Assert.Equal(expectedHex, Write(geometry, isGeography: true));
Expand All @@ -98,7 +107,7 @@ public void Write_works_when_IsGeography(string wkt, string expectedHex)
[Fact]
public void Write_throws_when_IsGeography_and_shell_oriented_clockwise()
{
var geometry = new WKTReader().Read("POLYGON ((0 0, 0 1, 1 1, 0 0))");
var geometry = new WKTReaderEx().Read("POLYGON ((0 0, 0 1, 1 1, 0 0))");
geometry.SRID = 4326;

var ex = Assert.Throws<ArgumentException>(
Expand All @@ -110,7 +119,7 @@ public void Write_throws_when_IsGeography_and_shell_oriented_clockwise()
[Fact]
public void Write_throws_when_IsGeography_and_hole_oriented_counter_clockwise()
{
var geometry = new WKTReader().Read("POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))");
var geometry = new WKTReaderEx().Read("POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))");
geometry.SRID = 4326;

var ex = Assert.Throws<ArgumentException>(
Expand Down Expand Up @@ -195,20 +204,6 @@ public void HandleOrdinates_works()
Write(point, Ordinates.XY));
}

[Theory]
[InlineData("CIRCULARSTRING (0 0, 1 1, 2 0)")]
[InlineData("COMPOUNDCURVE ((0 0, 1 0), CIRCULARSTRING (1 0, 2 1, 3 0))")]
[InlineData("CURVEPOLYGON (CIRCULARSTRING (2 1, 1 2, 0 1, 1 0, 2 1))")]
[InlineData("FULLGLOBE")]
public void Types_still_unknown(string wkt)
{
var reader = new WKTReader();

// NB: If this doesn't throw, we're unblocked and can add support
Assert.Throws<ParseException>(
() => reader.Read(wkt));
}

private string Write(
Geometry geometry,
Ordinates handleOrdinates = Ordinates.XYZM,
Expand Down