【问题标题】:Create geography polygon from points in T-SQL从 T-SQL 中的点创建地理多边形
【发布时间】:2012-04-02 02:58:36
【问题描述】:

在 Azure 上的我的 SQL Server (2008 R2) 中,有一个表包含大量地理 Points(纬度/经度):

CREATE TABLE MyPoints
(
  Region uniqueidentifier NOT NULL,
  Number int NOT NULL,
  Position geography NOT NULL,
  CONSTRAINT PK_MyPoints PRIMARY KEY(Region, Number)
)

现在我想从这些点创建一个Polygon 以确定我的哪些商店位于这些点定义的区域内。

在 T-SQL 中是否有一种从给定点构建多边形的本机且快速的方法? The solutions I found 正在使用 STGeomFromText/STGeomFomWKB 方法来创建多边形,这对我来说似乎很麻烦而且很慢。

类似:

SET @POLY = geometry::STPolyFromPoints(SELECT Position FROM MyPoints)

【问题讨论】:

    标签: sql-server tsql sql-server-2008-r2 geography


    【解决方案1】:

    假设我们在这张表中有一个完整的表,其中包含有序的经纬度:

    CREATE TABLE [dbo].[LongAndLats](
        [Longitude] [decimal](9, 6) NULL,
        [Latitude] [decimal](9, 6) NULL,
        [SortOrder] [int] NULL
        )
    

    这会将这些点转换为多边形:

    DECLARE @BuildString NVARCHAR(MAX)
    SELECT @BuildString = COALESCE(@BuildString + ',', '') + CAST([Longitude] AS NVARCHAR(50)) + ' ' + CAST([Latitude] AS NVARCHAR(50))
    FROM dbo.LongAndLats
    ORDER BY SortOrder
    
    SET @BuildString = 'POLYGON((' + @BuildString + '))';  
    DECLARE @PolygonFromPoints geography = geography::STPolyFromText(@BuildString, 4326);
    SELECT @PolygonFromPoints
    

    一些注意事项:

    • 多边形需要闭合。 IE。第一点和最后一点应该相同。
    • 应至少获得 4 分。
    • 点的顺序很重要。它应该遵循“左手/脚规则”(位于点之间绘制的线左侧的区域被视为在多边形内)

    【讨论】:

    • 我很想知道如何进行实际的排序部分,因为您的上述解决方案很棒。我的挂断是如何对“左手/脚规则”中的点进行排序。我最终得到了一个自身重叠的多边形,因为我的纬度/经度排序不正确。
    • 示例:DECLARE @geom GEOMETRY = ' POLYGON (( -116.77953600883484 33.103710174560547 ,-117.03299999237061 32.547900199890137 ,-117.11846709251404 33.469111442565918 ,-117.38499999046326 33.202700138092041 ,-117.38700008392334 33.206999778747559 ,-117.39700007438660 33.209300041198730 ,-116.77953600883484 33.103710174560547 ))' DECLARE @geog GEOGRAPHY = @geom.MakeValid().STUnion(@geom.MakeValid().STStartPoint()).STAsText() select @geog
    • @Smitty,在插入[dbo].[LongAndLats] 表之前应该知道顺序。如果点未排序,我不知道有任何方法可以确定可靠的非相交排序顺序,我认为这是不可能的,因为可能有 n 个可能的排序顺序。
    • 我的情况是我在整个城市都有一系列随机纬度/经度点。最外面的点(即离“中心”最远的点)是我试图从中制作形状/多边形的点。我基本上是从一堆随机的纬度/经度点建立市场边界,但我必须“扔掉”市场中间的点,只保留最外面的点来创建多边形。我已经在某种程度上使用 .Reduce() 完成了此操作,但由于我的排序错误而无法获得有效的多边形。我不得不认为这是一个普遍的问题.. 你怎么会建立国家等的形状文件。
    • 你可以使用 STEnvelope() 来创建一些粗糙的东西。例如DECLARE @geom GEOGRAPHY = ' POLYGON (( -116.77953600883484 33.103710174560547 ,-117.03299999237061 32.547900199890137 ,-117.11846709251404 33.469111442565918 ,-117.38499999046326 33.202700138092041 ,-117.38700008392334 33.206999778747559 ,-117.39700007438660 33.209300041198730 ,-116.77953600883484 33.103710174560547 ))'; SET @geom = @geom.MakeValid() DECLARE @boundingbox geometry = geometry::STGeomFromWKB(@geom.STAsBinary(), @geom.STSrid).STEnvelope(); SELECT geography::STGeomFromWKB(@boundingbox.STAsBinary(), @boundingbox.STSrid);
    【解决方案2】:

    据我所知,没有将表格作为参数并将其转换为多边形的本机函数。

    您最好将标量用户定义函数与您已经阅读过的 STPolyFromText 结合起来,将一列结果连接成一个逗号分隔的字符串。

    UDF to Concatenate Column to CSV String

    MSDN - STPolyFromText

    【讨论】:

    • 我们正在使用一个函数来连接二进制表示中的点,并在该字符串上调用STGeomFromWKB。它对我们的目的来说已经足够快了,但它仍然很丑。
    • 另一个建议是编写您自己的 .NET CLR 用户定义函数,该函数采用表参数(实际地理点的列)并返回几何。我还没有使用它,但 SqlGeometryBuilder 看起来很有希望:msdn.microsoft.com/en-us/library/…
    • AFAIK 不支持 SQL Azure 上的 CLR 函数。我也想过这种可能性。
    • 哎呀,我错过了 Azure 参考。是的,字符串连接可能是你现在唯一的选择。花点时间在 SQL Server Connect 上请求此功能! connect.microsoft.com/SQLServer/Feedback
    猜你喜欢
    • 2019-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    相关资源
    最近更新 更多