【问题标题】:STContains - tests failing for points INSIDE polygonSTContains - 对多边形内的点进行测试失败
【发布时间】: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) o​​n 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 内点失败。

标签: sql-server sqlgeography


【解决方案1】:

因为在球面几何中,纬线不是直线。大圆弧是。您的多边形最近的边是-122.906113 48.998367, -95.169068 48.966372,它位于北纬 49 度纬线的 -103 经度处。

select geography::STLineFromText('LINESTRING(-122.906113 48.998367, -95.169068 48.966372)', 4326);

【讨论】:

  • 先生。布朗 - 你再一次通过!那么,我们如何“调整”以使用带有 SQL 地理类型的墨卡托投影,以便在 Bing 或 Google 地图上直观地显示落在多边形内的点?此外——如果有办法在 SSMS 的空间视图中同时显示多边形和点——“答案”将是显而易见的。有什么方法可以在空间视图中同时显示一个多边形和一个点?
  • 我尝试了所有我能想到的方法来显示两者,然后才开始绘制最近的边缘。也许是 SSMS 反馈项:aka.ms/sqlfeedback.
  • 已经完成——对空间视图的简单更改将允许我们选择多列进行显示(而不是当前实现的单列)将是一个非常受欢迎的功能。再次感谢!!
猜你喜欢
  • 1970-01-01
  • 2013-03-26
  • 1970-01-01
  • 2016-02-23
  • 2011-11-14
  • 2018-12-12
  • 2012-02-21
  • 2015-04-07
  • 1970-01-01
相关资源
最近更新 更多