问题
I know how to compose a SqlGeometry
using SqlGeometryBuilder
, for example:
// using Microsoft.SqlServer.Types;
SqlGeometryBuilder geometryBuilder = new SqlGeometryBuilder();
geometryBuilder.SetSrid(…);
geometryBuilder.BeginGeometry(OpenGisGeometryType.Polygon);
geometryBuilder.BeginFigure(0, 0);
geometryBuilder.AddLine(…);
…
geometryBuilder.EndFigure();
geometryBuilder.EndGeometry();
SqlGeometry geometry = geometryBuilder.ConstructedGeometry;
Once a SqlGeometry
is built, it's pretty much an opaque object, and inspecting its constituent parts (e.g. the line segments its boundary is made up from, and those lines' end points) using the ST…
methods methods (STNumPoints
, STPointN
, STNumCurves
, STCurveN
, STBoundary
, etc.) feels a little cumbersome to me.
Is there something in Microsoft.SqlServer.Types
or the .NET Framework Class Library that is the logical opposite of SqlGeometryBuilder
, i.e. something that I could use to decompose a SqlGeometry
into its constituent parts? I imagine that what I am looking for might possibly make use of the visitor pattern.
回答1:
The Microsoft.SqlServer.Types
API does offer functionality opposite to SqlGeometryBuilder
, in the form of the SqlGeometry.Populate(IGeometrySink110) method.
This method accepts an object implementing the IGeometrySink110 interface, whose definition very closely mirrors that of SqlGeometryBuilder
. The method will "replay" the method calls that were used on a SqlGeometryBuilder
in order to construct the SqlGeometry
.
For example, given the SqlGeometry geometry
as shown in the question above, as well as the following IGeometrySink110
implementation:
class ConsoleGeometrySink : IGeometrySink110
{
public void SetSrid(int srid)
{
Console.WriteLine($"SetSrid(srid: {srid})");
}
public void BeginGeometry(OpenGisGeometryType type)
{
Console.WriteLine($"BeginGeometry(type: {type})");
}
public void BeginFigure(double x, double y, double? z, double? m)
{
Console.WriteLine($"BeginFigure(x: {x}, y: {y}, z: {z}, m: {m})");
}
public void AddCircularArc(double x1, double y1, double? z1, double? m1,
double x2, double y2, double? z2, double? m2)
{
Console.WriteLine($"AddCircularArc(x1: {x1}, y1: {y1}, z1: {z1}, m1: {m1}, " +
$"x2: {x2}, y2: {y2}, z2: {z2}, m2: {m2})");
}
public void AddLine(double x, double y, double? z, double? m)
{
Console.WriteLine($"AddLine(x: {x}, y: {y}, z: {z}, m: {m})");
}
public void EndFigure()
{
Console.WriteLine($"EndFigure()");
}
public void EndGeometry()
{
WriteLine($"EndGeometry()");
}
}
Calling geometry.Populate(new ConsoleGeometrySink())
would output the following:
SetSrid(srid: …)
BeginGeometry(type: Polygon)
BeginFigure(x: 0, y: 0, z: , m: )
AddLine(…)
…
EndFigure()
EndGeometry()
which mirrors exactly the original steps performed to build the SqlGeometry
.
来源:https://stackoverflow.com/questions/40854218/looking-for-the-opposite-of-sqlgeometrybuilder-how-can-i-decompose-a-sqlgeometr