You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Transact SQL geography多边形STContains判断结果异常问题问询

问题原因与解决方案

你的问题核心在于SQL Server geography类型的多边形环方向规则:

  • geography基于球面坐标系,多边形的环方向直接决定它代表的区域:
    • 逆时针外环对应环内的小区域(即你预期的卢森堡范围)
    • 顺时针外环则对应整个地球表面减去环内小区域(相当于“反多边形”)

你自认为是逆时针创建的多边形,但实际点的顺序是顺时针(右上→左上→左下→右下→右上),导致这个多边形实际代表“地球除卢森堡外的所有区域”,所以布鲁塞尔的点也被包含在内,STContains返回true。

解决方法

有两种方式可以修正:

1. 反转点顺序,改为逆时针

调整插入@points表的点顺序,让环按逆时针方向绘制:

declare @points table (locationcode nvarchar(max), latitude real, longitude float, info nvarchar(max), ord int)
declare  @locationcode nvarchar(max) = 'LUX'
insert into @points values
    ('LUX', 50.264980, 6.650216, 'right top', 1),
    ('LUX', 49.322218, 6.657984, 'right bottom', 2),
    ('LUX', 49.307025, 5.430560, 'left bottom', 3),
    ('LUX', 50.294766, 5.345107, 'left top', 4),
    ('LUX', 50.264980, 6.650216, 'right top', 5)

declare @buildstring nvarchar(max)
select @buildstring = coalesce(@buildstring + ', ','') + convert(nvarchar,latitude) + ' ' +  convert(nvarchar,longitude) from @points where locationcode = @locationcode order by ord
declare @polygon geography = 'POLYGON((' + @buildstring + '))'
print 'polygon:'
print @polygon.ToString()
print @polygon.STIsValid()
-- point in polygon coordinates:
declare @pointInLatitude float
declare @pointInLongitude float
declare  @pointIn geography
-- point out of polygon coordinates:
declare @pointOutLatitude float
declare @pointOutLongitude float
declare @pointOut geography
-- +/- center Luxembourg city (Luxembourg):
set @pointInLatitude = 49.609133
set @pointInLongitude = 6.136210
set @pointIn = geography::Point(@pointInLatitude, @pointInLongitude, 4326)
-- +/- center Brussels city: (Belgium)
set @pointOutLatitude = 50.847726
set @pointOutLongitude = 4.349612
set @pointOut = geography::Point(@pointOutLatitude, @pointOutLongitude, 4326)

select @polygon.STContains(@pointIn) , @polygon.STContains(@pointOut)

2. 使用ReorientObject()反转多边形环方向

如果不想修改点顺序,可在创建多边形后调用ReorientObject()自动反转环方向:

declare @points table (locationcode nvarchar(max), latitude real, longitude float, info nvarchar(max), ord int)
declare  @locationcode nvarchar(max) = 'LUX'
insert into @points values
    ('LUX', 50.264980, 6.650216, 'right top', 1),
    ('LUX', 50.294766, 5.345107, 'left top', 2),
    ('LUX', 49.307025, 5.430560, 'left bottom', 3),
    ('LUX', 49.322218, 6.657984, 'right bottom', 4),
    ('LUX', 50.264980, 6.650216, 'right top', 5)

declare @buildstring nvarchar(max)
select @buildstring = coalesce(@buildstring + ', ','') + convert(nvarchar,latitude) + ' ' +  convert(nvarchar,longitude) from @points where locationcode = @locationcode order by ord
declare @polygon geography = 'POLYGON((' + @buildstring + '))'
-- 反转环方向,修正多边形代表的区域
set @polygon = @polygon.ReorientObject()
print 'polygon:'
print @polygon.ToString()
print @polygon.STIsValid()
-- point in polygon coordinates:
declare @pointInLatitude float
declare @pointInLongitude float
declare  @pointIn geography
-- point out of polygon coordinates:
declare @pointOutLatitude float
declare @pointOutLongitude float
declare @pointOut geography
-- +/- center Luxembourg city (Luxembourg):
set @pointInLatitude = 49.609133
set @pointInLongitude = 6.136210
set @pointIn = geography::Point(@pointInLatitude, @pointInLongitude, 4326)
-- +/- center Brussels city: (Belgium)
set @pointOutLatitude = 50.847726
set @pointOutLongitude = 4.349612
set @pointOut = geography::Point(@pointOutLatitude, @pointOutLongitude, 4326)

select @polygon.STContains(@pointIn) , @polygon.STContains(@pointOut)

验证结果

两种方法执行后,STContains(@pointIn)返回1(卢森堡点在多边形内),STContains(@pointOut)返回0(布鲁塞尔点在多边形外),符合预期。

内容的提问来源于stack exchange,提问作者Serge Van Cleynenbreugel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:35:54