更改SQL 2008的多边形“手性”(反转多边形顶点顺序)


11

我有几百个形状(polygons和multipolygons),每个形状都由数以万计的点组成,这些点正试图进入SQL 2008。

不幸的是,我尝试导入的形状是“右旋”的(每个形状的周长围绕其包含的点顺时针绘制)。SQL Server至少对于geography类型采用“左手”形状(围绕内部逆时针旋转)。这意味着SQL假定我要选择形状之外的整个地球。有人将其描述为“由内而外”的形状。

MSDN来看,令人沮丧的是没有说要使用哪种环定向:

如果使用geography数据类型存储空间实例,则必须指定环的方向并准确描述实例的位置。

如果您在SQL 2008中使用错误的环向,它将崩溃并显示以下错误(强调我的意思):

用户定义的例程或聚合“地理”的执行过程中发生了.NET Framework错误:Microsoft.SqlServer.Types.GLArgumentException:24205:指定的输入不代表有效的地理实例,因为它超出了一个半球。每个地理实例必须适合一个半球。导致此错误的常见原因是多边形的环方向错误。

导入形状geometry而不是导入形状geography效果很好,但我想使用geography

在SQL 2012中,解决此问题显得微不足道,但我与2008紧密相关。

我应该如何转换形状?


1
+1个大问题...您是否有一个链接,其中说Sql Server采取惯用左手的形状?
Kirk Kuykendall

@柯克谢谢。我在查找官方文档时遇到了麻烦,但是我可以链接到MSDN,在该MSDN上它说“环向”很重要(尽管它没有说明使用哪种方式)。我还将输入一个崩溃时发生的错误。
Michael-Clay Shirky在哪里,

Answers:


14

Spatial Ed的博客提供了一个简洁的解决方案。这是一些演示转换的SQL:

DECLARE @geom GEOMETRY = 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))';
DECLARE @geog GEOGRAPHY = @geom.MakeValid().STUnion(@geom.STStartPoint()).STAsText()

摘自Ed的文章:

这种行为的关键是STUnion()方法。由于这是一种基于OGC的方法,可以处理给定特征的整个几何图形,因此它会迫使多边形进入该方法所需的方向-碰巧是该Geography类型所使用的方向。图示的这种方法非常有效,使开销很小。


2
在SQL Server 2008 r2上,我还必须将.MakeValid()放在STUnion()的内部,以使其正常工作:.STUnion(@ geom.MakeValid()。STStartPoint())
克里斯·史密斯

@Smitty对于SQL无法确定起点的情况很有用。也许形状再翻一番,还是其他奇怪的情况?
Michael-Clay Shirky在哪里

是的,在我的情况下,形状很古怪并且相互重叠。
克里斯·史密斯

0

在> = SQL Server 2012中,ReorientObject()方法应完成此任务。对于<SQL Server 2012,下面是另一种方法。

对于现有的SQL地理@g,以下代码将提取点并以相反的顺序重新创建具有点(顶点)的多边形:(
注意1:适用于简单的多边形,不适用于多边多边形或具有环/形心的多边形)
(注意2:使用SRID 4326(WGS 84)坐标系)

--For existing geography @g
DECLARE @GeometryText varchar(max), @ReversedPolygon geography
DECLARE @GeometryType varchar(20) = 'POLYGON', @Count int
SET @Count = @g.STNumPoints()
WHILE @Count > 0
BEGIN
    SET @GeometryText = @GeometryText + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Long)) + ' ' + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Lat))
    SET @Count = @Count - 1
    IF @Count > 0 SET @GeometryText = @GeometryText + ','
END
SET @GeometryText = @GeometryType +'((' + @GeometryText + '))'
SET @ReversedPolygon = geography::STGeomFromText(@GeometryText, 4326); 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.