Looking for the opposite of SqlGeometryBuilder: How can I decompose a SqlGeometry?

感情迁移 提交于 2020-01-07 02:50:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!