将几何转换为地理时出错

Errors converting Geometry to Geography

我在尝试将数据从几何字段转换为单独 table 中的地理字段时遇到错误。

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))%'

有效。

所以我将所有非地理数据移动到新的 table 并开始逐个记录地查看哪个 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

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

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

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

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 服务器文档中的 Spatial Data Types Overview

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

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

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