SQL空间多边形内外颠倒

12

我正在允许用户通过单击来绘制Silverlight中的多边形。然后我循环遍历这些点,将它们转换为经度和纬度,然后保存到 SQL 中 (geography 列)。

问题在于,由于地球是圆的,所以只有当用户顺时针绘制时才能正常工作。否则它会尝试使多边形绕着世界转一圈并失败。

因此,我应该如何正确地做到这一点?我必须确定他们绘制的方向吗?如果是这样,我该如何确定方向?

5个回答

11

如果地理图形的EnvelopeAngle()方法返回180,则可以使用ReorientObject()函数进行纠正。

以下是示例:

--A CW polygon
DECLARE @G3 GEOGRAPHY = 'POLYGON ((45 45, 44 45, 44 46, 45 46, 45 45))';    
SELECT @G3.EnvelopeAngle();                --180
SELECT @G3.ReorientObject().STAsText();    --POLYGON ((44 46, 44 45, 45 45, 45 46, 44 46))

编辑 根据评论中的说明,您可以使用一个简单的更新命令来纠正当前的几何形状(在您确定它们不正确的情况下):

UPDATE foo_table SET bar_column = bar_column.ReorientObject() 
    WHERE bar_column.EnvelopeAngle() > 90

非常好的答案。你刚刚救了我的一天。 - Pablo Claus
@Pabloker 很高兴能够帮到你。你可能也想看看这个链接 link - Hossein Narimani Rad
1
如果您有现有条目,则以下查询可帮助:UPDATE foo_table SET bar_column = bar_column.ReorientObject() WHERE bar_column.EnvelopeAngle() > 90 - jhhwilliams

2
最近我在GIS StackExchange上问了一个类似的问题。我相信我已经找到了一个仅使用SQL的解决方案,如下所示:
最终在Spatial Ed's Blog上找到了答案。
以下是演示变换的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的方法,可以在给定要素的整个几何体上工作,它会强制将多边形放置到所需的方法方向上 - 这恰好是用于地理类型的方向[...]。这种方法非常高效,可以保持开销较小[...]。

你是怎么在2008上实现这个的?我得到了“无法找到类型为'Microsoft.SqlServer.Types.SqlGeography'的'MakeValid'方法”的错误。 - capdragon
@capdragon:你尝试在“几何”或“地理”上使用MakeValid()了吗? - Michael
地理信息。我和你处于类似的情况。我有几何图形,投影并转换到一个单独的要素类中,但现在我遇到了“每个地理实例必须适合单个半球”的错误。这种错误的常见原因是多边形具有错误的环向。 - capdragon
1
哦,我明白了。我应该在几何上做这个。 - capdragon
我如何使用变量选择来完成这个操作?例如,我的POLYGON((X Y, X Y, X Y))字符串在一个表中。我不会手动声明每个多边形。 - Zachary Ordo - GISP
@ZacharyOrdo-GISP 您的 polygon 是一个字符串还是一个 geometry 对象?如果是后者,您可以尝试使用 CAST(foo_column.MakeValid().StUnion(foo_column.STStartPoint()).STAsText() AS GEOGRAPHY) 进行转换。其次,如果您使用的 SQL Server 版本高于 2008,则可以在 我的 GIS.SE 问题 中使用 链接 中的 ReorientObject()。最后,如果可能的话,请在保存之前进行重新定向,而不是在读取时进行。 - Michael

1

如果您使用的是SqlServer 2008的RTM版本,您可以随时使用codeplex上的sqlspatial工具,该工具可自由分发,并且从该库中只需使用makevalid方法即可。

如果您有时间尝试SqlServer Denali的CTP1版本,您可以选择新的空间类型,这些类型可以接受大于半球体积的对象,并且具有ReorientObject方法,以便在需要时重新定位对象 :)


0

左手定则控制着这个问题...当你“走”多边形的周长时,你的左手必须始终在内部...所以事物应该“看起来”是逆时针数字化的。对于带孔的甜甜圈和多边形也是如此。

如果你把左手放在感兴趣的多边形区域内,它们将以顺时针方式数字化。

确定哪一个是正确的简单方法是始终选择面积较小的那个...在我能想到的任何工作流程中,没有多边形会被数字化为大于世界一半的大小...

工作流程如下:让用户创建他们的多边形,创建另一个具有相反方向的多边形(在SQL Server中使用ReorientObject()),然后比较它们的面积...逻辑上,最小的是正确的。

这只是解决这个问题的另一种方法。


0

这是地理空间数据类型中的一个常见概念,多边形由许多顶点和连接这些顶点的边所定义。然而,你必须能够区分多边形内部和外部的内容。这是通过系统假设边的一侧将始终定义内部来完成的(不同的标准使用左侧或右侧)。

在一个方向上,你画了一个小圆圈,在另一个方向上,你画了一个包围整个世界的球体,除了一个小圆圈。后者往往会打破地理限制并引发异常。

如果你考虑尝试画一个甜甜圈,你有两个多边形,并且必须按顺时针/逆时针的方式放置点,以定义中心的“孔”。


是的,我意识到了。但是我该怎么办? - Matt
你必须按照适当的顺序阅读它们,但忽略绘制点的顺序。 - Andrew
在stackoverflow上询问这个问题的帖子数量:https://dev59.com/dnVC5IYBdhLWcg3wnCWA 例如。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接