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

I know how to compose 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; 

After creating SqlGeometry it is a rather opaque object and checks its components (for example, the segments of the lines that make up its border and the endpoints of these lines) using the methods of the ST… methods ( STNumPoints , STPointN , STNumCurves , STCurveN , STBoundary , etc. .) feels a little bulky for me.

Is there something in Microsoft.SqlServer.Types or the .NET Framework class library that is the logical opposite of SqlGeometryBuilder , that is, something I could use to decompose SqlGeometry into its component parts? I assume that what I am looking for might use a visitor pattern.

0
source share
1 answer

The Microsoft.SqlServer.Types API offers functionality opposite to SqlGeometryBuilder in the form of SqlGeometry.Populate(IGeometrySink110) .

This method accepts an object that implements the IGeometrySink110 interface , the definition of which very closely reflects the value of SqlGeometryBuilder . The method will β€œplay back” the method calls that were used in the SqlGeometryBuilder to build the SqlGeometry .

For example, given the SqlGeometry geometry , as shown in the question above, as well as the following implementation of IGeometrySink110 :

 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()"); } } 

A call to geometry.Populate(new ConsoleGeometrySink()) outputs the following:

 SetSrid(srid: …) BeginGeometry(type: Polygon) BeginFigure(x: 0, y: 0, z: , m: ) AddLine(…) … EndFigure() EndGeometry() 

which accurately reflects the initial steps taken to build the SqlGeometry .

+1
source

All Articles