【发布时间】:2020-05-11 16:36:59
【问题描述】:
一、SQL版本:
Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (X64) Apr 29 2016 23:23:58 版权所有 (c) Microsoft Corporation Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 (Build 9600: ) (管理程序)
我声明了一个封闭的多边形(使用左手规则正确定向),根据 SQL 是有效的:
DECLARE @g geography;
SET @g = geography::STPolyFromText('POLYGON((-141.251221 60.177476, -134.351807 52.952478, -124.859620 48.440718, -123.623658 48.163009, -123.132020 48.232578, -122.906113 48.998367, -95.169068 48.966372, -94.980927 49.021337, -94.627991 48.700606, -93.907013 48.594450, -93.845215 48.495351, -93.510132 48.517642, -93.197022 48.583549, -92.743836 48.507408, -92.422486 48.211991, -91.573792 48.021520, -90.973664 48.095065, -90.146256 48.021693, -89.428711 47.911409, -88.442688 48.232120, -84.935303 46.850463, -84.819947 46.614678, -84.531556 46.397991, -84.200593 46.493917, -84.117508 46.124608, -83.620034 45.782175, -82.591267 45.290317, -82.166749 43.592965, -82.661133 42.606311, -82.886353 42.391659, -83.097840 42.332805, -83.187104 42.071357, -83.135605 41.842088, -82.865410 41.657411, -82.463379 41.587347, -81.068116 42.119252, -80.049134 42.334835, -78.887330 42.783953, -78.868104 42.953046, -78.995820 43.161758, -79.090577 43.433616, -78.664856 43.557148, -76.766968 43.541223, -76.398926 44.064539, -74.852601 44.971250, -71.471558 44.957647, -70.846711 45.205884, -70.589219 45.379779, -70.207787 45.900179, -69.238587 47.291005, -68.891488 47.116066, -68.297196 47.291936, -67.850361 47.016678, -67.864953 45.667941, -65.966034 43.191802, -49.229737 45.124550, -59.425049 68.026407, -75.421143 74.789051, -73.663331 78.324047, -57.315674 82.569900, -71.378174 83.545629, -112.335206 79.852216, -141.163331 70.394745, -141.251221 60.177476 ))', 4326);
SELECT @g.IsValidDetailed() AS 'IsValidDetailed', @g.STIsClosed() AS 'STIsClosed', @g.EnvelopeAngle() AS 'EnvelopeAngle';
当上述查询被执行时,SQL 会响应:
IsValidDetailed STIsClosed EnvelopeAngle
24400: Valid True 33.0780372828377
为了进行视觉验证,我绘制了多边形(通过 Google 地图),并且还包括了多边形内部的 3 个点以及多边形外部的 3 个点。下面是多边形的屏幕快照,并指向显示完整多边形的缩放级别(红色区域表示包围多边形的“边界”):
放大地图,可以开始看到各个点,即:
进一步放大,可以看到其中两个点非常靠近多边形的边缘,一个在里面(绿色),一个在外面(红色):
以下查询用于测试多边形内部的点:
SELECT lat, lon,
@g.STContains( geography::Point( lat, lon, 4326 ) ) AS STContains,
geography::Point( lat, lon, 4326 ).STWithin( @g ) AS STWithin
FROM ( VALUES ( 49.119404, -102.988586 ),
( 49.004776, -102.996875 ),
( 48.975416, -103.005152 )
) points( lat, lon )
SQL 响应:
lat lon STContains STWithin
49.119404 -102.988586 False False
49.004776 -102.996875 False False
48.975416 -103.005152 False False
-- 期待 STContains 和 STwithin 为多边形内的点返回“True”???
以下查询用于测试多边形外的点:
SELECT lat, lon,
@g.STContains( geography::Point( lat, lon, 4326 ) ) AS STContains,
geography::Point( lat, lon, 4326 ).STWithin( @g ) AS STWithin
FROM ( VALUES ( 48.975409, -103.005151 ),
( 48.974153, -103.005144 ),
( 48.951739, -103.005627 )
) points( lat, lon )
SQL 响应:
lat lon STContains STWithin
48.975409 -103.005151 False False
48.974153 -103.005144 False False
48.951739 -103.005627 False False
-- 预期结果,因为所有点都在多边形之外。
问题:
为什么 STContains / STWithin 对于多边形内部的点会失败?
我必须假设我做错了什么,但我遵循了构建多边形的规则(左手边),并且 SQL 指示多边形是“有效的”。
任何建议将不胜感激。
【问题讨论】:
-
您确定您使用的是左手方向吗?如果您先
SET @g = @g.ReorientObject(),您的预期结果会改变吗? -
@AlwaysLearning - 使用 EnvelopeAngle 作为启发式方法,如果方向不正确,我希望它更接近(如果不完全)180°。在其他新闻中,加拿大是大。
-
@g.STDistance( geography::Point( lat, lon, 4326 ))对您期望在多边形内和多边形外的点集返回什么? -
@AlwaysLearning - 是的,我检查了包络角 (
-
@BenThul - 我希望内部点与 g.EnvelopeCenter 的距离小于外部点的距离,即: g.EnvelopeCenter().STDistance( geography::Point( lat, lon, 4326 )) AS STDistance - 尝试并确认 - 内部点的距离都小于外部点的距离。仍然没有答案为什么 STContains / STWithin 内点失败。