STContains - tests failing for points INSIDE polygon

元气小坏坏 提交于 2020-06-17 15:12:35

问题


First, SQL version:

Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (X64) Apr 29 2016 23:23:58 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 (Build 9600: ) (Hypervisor)

I declare a single closed polygon (correctly oriented using left-hand rule), which according to SQL is valid:

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';

When the above query is executed, SQL responds with:

IsValidDetailed STIsClosed  EnvelopeAngle
24400: Valid    True        33.0780372828377

For visual verification, I plotted the polygon (via Google maps) and also included 3 points INSIDE the polygon, as well as 3 points OUTSIDE the polygon. Below is a screen snapshot of the polygon and points at a zoom level that shows the full polygon (the red area denotes the "bounds" that enclose the polygon):

Zooming in on the map, you can start to see the individual points, i.e.:

Zooming in further, you can see two of the points are very close to the edge of the polygon, one inside (green), one outside (red):

The following query was used to test for points that are INSIDE the polygon:

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 responds with:

lat         lon         STContains  STWithin
49.119404   -102.988586 False       False
49.004776   -102.996875 False       False
48.975416   -103.005152 False       False

-- Was expecting STContains and STwithin to return "True" for points inside the polygon???

The following query was used to test for the points OUTSIDE of the polygon:

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 responds with:

lat         lon         STContains  STWithin
48.975409   -103.005151 False       False
48.974153   -103.005144 False       False
48.951739   -103.005627 False       False

-- Expected results as all points are OUTSIDE of the polygon.

Question:

Why is STContains / STWithin failing for points that are INSIDE the polygon?

I must assume I am doing something wrong, but I have followed the rules (left-hand) for constructing the polygon and SQL indicates the polygon is "valid".

Any advice would be appreciated.


回答1:


Because in spherical geometry, lines of latitude are not straight lines. Great circle arcs are. The nearest edge of your polygon is -122.906113 48.998367, -95.169068 48.966372, which is well north of the 49th parallel at -103 longitude.

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

is



来源:https://stackoverflow.com/questions/61734711/stcontains-tests-failing-for-points-inside-polygon

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!