【问题标题】:Errors converting Geometry to Geography将几何转换为地理时出错
【发布时间】:2021-10-08 11:09:52
【问题描述】:

尝试将数据从几何字段转换为单独表中的地理字段时出错。

INSERT INTO PIGeoData
        ([ID], [geo_name], [geo_wkt] ,[port_geography_binary] )
SELECT  [id], [name] ,[wkt], GEOGRAPHY::STGeomFromWKB(em_ports.geom.STAsBinary(),4326)
FROM [guest].[em_ports]
where ID < 4548 and ID not in (select ID from PIGeoData)

我得到的错误是这样的

Msg 6522, Level 16, State 1, Line 1
A .NET Framework error occurred during execution of user-defined routine or aggregate "geography": 
Microsoft.SqlServer.Types.GLArgumentException: 24205: The specified input does not represent a valid geography instance because it exceeds a single hemisphere. Each geography instance must fit inside a single hemisphere. A common reason for this error is that a polygon has the wrong ring orientation. To create a larger than hemisphere geography instance, upgrade the version of SQL Server and change the database compatibility level to at least 110.
Microsoft.SqlServer.Types.GLArgumentException: 
   at Microsoft.SqlServer.Types.GLNativeMethods.ThrowExceptionForHr(GL_HResult errorCode)
   at Microsoft.SqlServer.Types.GLNativeMethods.GeodeticIsValid(GeoData& g, Double eccentricity, Boolean forceKatmai)
   at Microsoft.SqlServer.Types.SqlGeography.IsValidExpensive(Boolean forceKatmai)
   at Microsoft.SqlServer.Types.SqlGeography..ctor(GeoData g, Int32 srid)
   at Microsoft.SqlServer.Types.SqlGeography.GeographyFromBinary(OpenGisType type, SqlBytes wkbGeography, Int32 srid)

如果我尝试使用 WKT 进行转换,我会收到相同的消息

      ,GEOGRAPHY::STGeomFromText(wkt,4326)

这两种格式都来自 MS 文档here

但是如果我从 wkt 复制多边形数据并将其粘贴到这样的查询中

declare @sGeo  geography
declare @sWKT varchar(max)
select @sWKT = wkt from guest.em_ports where wkt like '%POLYGON ((73.50667 4.181667,73.50667 4.21,73.48 4.21,73.48 4.1783333,73.50667 4.181667,73.50667 4.181667))%'
set @sGeo = geography::STPolyFromText (@sWKT, 4326 )  
Update PIGeoData
Set PortBoundaries = @sGeo

Where wkt like '%POLYGON ((73.50667 4.181667,73.50667 4.21,73.48 4.21,73.48 4.1783333,73.50667 4.181667,73.50667 4.181667))%'

行得通。

所以我将所有非地理数据移到新表中,并开始逐条检查以查看哪个 WKT 失败了:

我使用了这个查询

Update PIGeoData
Set port_geography_binary = GEOGRAPHY::STGeomFromText(geo_wkt,4326)
where port_geography_binary is null and ID = <xyz>

其中 xyz 是单个记录 ID

这些 WKT 值成功

POLYGON ((-135.31197 59.451653,-135.32457 59.45799,-135.32996 59.454834,-135.36717 59.455154,-135.36452 59.449005,-135.36488 59.43996,-135.36697 59.43817,-135.33139 59.438065,-135.31197 59.451653,-135.31197 59.451653))

POLYGON ((-4.524549 48.365623,-4.518855 48.361416,-4.4854136 48.367413,-4.436236 48.381382,-4.420772 48.39644,-4.431077 48.398525,-4.4376454 48.393867,-4.438626 48.38611,-4.4559207 48.390007,-4.470995 48.387226,-4.4933248 48.384468,-4.499816 48.38401,-4.512855 48.3754,-4.524549 48.365623,-4.524549 48.365623))

这些 WKT 值失败

POLYGON ((-8.788489 37.773106,-8.989748 37.785244,-9.11148 37.93065,-9.01401 38.13953,-8.993956 38.30128,-9.266149 38.264282,-9.382366 38.33244,-9.435615 38.54836,-9.656681 38.602306,-9.683701 38.883057,-9.1720295 39.00796,-8.444215 39.550682,-8.213643 39.355015,-8.537656 38.037514,-8.712016 37.782127,-8.788489 37.773106))

POLYGON ((-119.71587 34.396824,-119.69837 34.410378,-119.67453 34.41837,-119.62994 34.420082,-119.63012 34.380177,-119.62986 34.3551,-119.71534 34.355022,-119.71587 34.396824,-119.71587 34.396824))

数据中对我来说没有什么明显的。谁能帮助解释为什么这些记录和数据失败?

TIA

【问题讨论】:

    标签: tsql sqlgeography wkt


    【解决方案1】:

    错误消息的相关部分是“此错误的常见原因是多边形的环方向错误。”

    失败的多边形按顺时针顺序排列。

    要将它们转换为逆时针顺序,您可以使用以下内容:

    DECLARE @t VARCHAR(MAX)='POLYGON ((-119.71587 34.396824,-119.69837 34.410378,-119.67453 34.41837,-119.62994 34.420082,-119.63012 34.380177,-119.62986 34.3551,-119.71534 34.355022,-119.71587 34.396824,-119.71587 34.396824))'
    
    DECLARE @x XML=REPLACE(REPLACE(REPLACE(@t,'POLYGON ((','<root><p>'),'))','</p></root>'),',','</p><p>')
    DECLARE @r VARCHAR(MAX)='POLYGON (('+STUFF((
        SELECT ','+q.Point
        FROM (
            SELECT n.value('.','varchar(50)') AS Point, ROW_NUMBER() OVER (ORDER BY t.n) AS Position
            FROM @x.nodes('/root/p') t(n)
        ) q ORDER BY q.Position DESC
        FOR XML PATH(''), TYPE
    ).value('.','VARCHAR(MAX)'),1,1,'')+'))'
    
    DECLARE @g GEOGRAPHY=GEOGRAPHY::STGeomFromText(@r,4326)
    SELECT @g, @g.ToString()
    

    后期编辑:

    有一个约定,即多边形应始终按逆时针顺序表示。想象一下,你有一个赤道形状的多边形;如果没有这个约定,就不清楚多边形代表北半球还是南半球。有关详细信息,请参阅 Microsoft SQL Server 文档中的Spatial Data Types Overview

    此外,当兼容性级别为 100 或更低时,SQL Server 中有一个限制,即每个地理实例必须适合单个半球。如果您使用的是 SQL Server 2012 或更高版本,并且您选择使用至少兼容级别 110,则可以避免错误消息,但多边形将代表您通常认为多边形所代表的区域之外的整个区域。

    如果您使用的兼容级别为 100 或更低,您可以使用TRY/CATCH 来检测错误,如果发生错误,您应该尝试反转多边形。

    如果您使用兼容级别 110 或更高版本,您可以尝试使用 STArea() 检查多边形的表面是否比一个半球大得多或小得多。如果面积接近 510100000000000 平方米(大约是整个地球的面积),那么您应该反转多边形。

    【讨论】:

    • 谢谢。现在这是有道理的。如何测试多边形是按顺时针还是逆时针顺序定义的?这是 Microsoft 实施的限制吗?还是最初定义多边形的人出错了?
    猜你喜欢
    • 2011-10-04
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    相关资源
    最近更新 更多