SQL Server STIntersects查询返回误报

时间:2014-08-10 13:42:54

标签: sql sql-server google-maps sqlgeography

问题

STIntersects正在返回误报

场景

  1. 我使用GoogleMaps绘制代表“伦敦拥堵费”区域的多边形,并将坐标保存到地理位置字段中的数据库
  2. 我从Google Directions API获取了一条路线
  3. 的折线
  4. 我检查折线是否与我存储的任何区域相交。
  5. 问题

    1. 伦敦附近有一条路线(避开它50英里)但STIntersects正在显示伦敦市中心伦敦拥堵费多边形的交叉点。
    2. 我知道折线很好,因为我可以在谷歌地图上渲染它并看到它。我也知道这不是问题(见后面)
    3. 多边形坐标似乎绝对正常(虽然我怀疑这里有些不对劲),因为当我在Google地图上直观地渲染多边形时,它会正确显示。
    4. 我认为多边形坐标是一个贡献因素,因为我尝试了以下内容:

      1. 我创建了两个完全独立的应用程序和数据库实例
      2. 我比其他人更具体地绘制了伦敦拥堵冲锋区(更多点)
      3. 虽然在视觉上它们看起来非常相似(它们都覆盖了伦敦拥堵费用区域),但是有更多积分的版本可以正常工作。折线可以直接传递到它旁边,而没有报告的交叉点,而具有较少点的版本会返回假折线的假阳性,距离它几英里(50英寸)。
      4. 这怎么可能?

        以下是重建问题的方法。

        将问题多边形添加到地理数据库字段:

        INSERT INTO Polygons (ZoneName,Coordinates) VALUES ('IDoNotWork',geography::STGeomFromText(‘POLYGON ((51.48822 -0.13046, 51.49763 -0.09613, 51.51045 -0.07828, 51.52242 -0.09064, 51.52583 -0.1181, 51.52071 -0.15106, 51.50361 -0.14626, 51.48822 -0.13046)) ', 4326))
        

        将工作多边形添加到地理数据库字段:

        INSERT INTO Polygons (ZoneName,Coordinates) VALUES ('IWork',geography::STGeomFromText('POLYGON ((51.51964 -0.16788, 51.5222 -0.15518, 51.52412 -0.14076, 51.52925 -0.12463, 51.52968 -0.12222, 51.5284 -0.11776, 51.53139 -0.11158, 51.52968 -0.09853, 51.52626 -0.08892, 51.52541 -0.08377, 51.51665 -0.07244, 51.50596 -0.07622, 51.49592 -0.08411, 51.49506 -0.09544, 51.49613 -0.09956, 51.49271 -0.103, 51.48844 -0.11227, 51.48673 -0.12119, 51.48758 -0.126, 51.49592 -0.14145, 51.49806 -0.14351, 51.49934 -0.14729, 51.50169 -0.14969, 51.50404 -0.14969, 51.51323 -0.15793, 51.51473 -0.16136, 51.51964 -0.16788))', 4326))
        

        使用stintersects SQL Query:

        运行此折线检查
         [Select ZonePolygonId, ZoneName  FROM dbo.Polygons  
          WHERE Coordinates.STIntersects(geography::STGeomFromText('LINESTRING (51.30835 -0.7802, 51.30856 -0.78056, 51.30865 -0.78066, 51.3093 -0.77954, 51.31049 -0.77735, 51.31125 -0.77586, 51.31149 -0.77572, 51.31149 -0.77573, 51.31149 -0.77576, 51.31151 -0.77578, 51.31153 -0.7758, 51.31156 -0.77581, 51.31161 -0.77574, 51.31161 -0.77564, 51.31159 -0.77561, 51.31172 -0.77532, 51.3122 -0.77494, 51.31275 -0.77437, 51.31331 -0.77363, 51.31351 -0.77179, 51.31395 -0.7678, 51.31424 -0.76718, 51.31496 -0.76648, 51.31609 -0.76546, 51.31621 -0.76533, 51.3154 -0.76344, 51.31424 -0.76016, 51.31237 -0.75621, 51.31193 -0.75574, 51.31045 -0.75527, 51.31023 -0.75506, 51.31001 -0.75484, 51.30957 -0.75449, 51.30903 -0.75363, 51.30864 -0.75257, 51.30846 -0.75148, 51.30862 -0.75088, 51.30865 -0.75022, 51.30861 -0.74951, 51.30936 -0.74848, 51.30971 -0.7482, 51.30979 -0.74818, 51.31035 -0.74823, 51.31157 -0.74911, 51.31311 -0.75048, 51.31361 -0.75105, 51.31429 -0.75224, 51.31464 -0.75328, 51.31449 -0.75371, 51.31447 -0.75439, 51.3147 -0.75463, 51.31561 -0.75462, 51.31654 -0.75584, 51.31702 -0.75665, 51.31764 -0.75776, 51.31778 -0.75856, 51.31764 -0.75913, 51.31705 -0.75958, 51.31669 -0.75948, 51.31641 -0.75906, 51.31629 -0.75852, 51.31638 -0.75767, 51.31687 -0.75598, 51.319 -0.74976, 51.3211 -0.74501, 51.32512 -0.73723, 51.32815 -0.73219, 51.33599 -0.71895, 51.33954 -0.71249, 51.34141 -0.709, 51.34306 -0.70635, 51.34485 -0.70398, 51.34605 -0.70264, 51.34792 -0.70054, 51.34854 -0.69965, 51.34963 -0.69756, 51.35113 -0.69318, 51.35289 -0.6881, 51.35592 -0.68078, 51.3575 -0.67668, 51.35856 -0.67201, 51.35893 -0.66851, 51.35895 -0.66475, 51.35863 -0.66067, 51.3586 -0.6577, 51.3592 -0.65349, 51.35984 -0.65129, 51.36167 -0.64633, 51.36357 -0.64179, 51.36563 -0.63772, 51.36673 -0.63515, 51.36762 -0.63231, 51.36933 -0.62452, 51.37112 -0.61722, 51.37285 -0.61133, 51.37588 -0.60193, 51.37759 -0.59701, 51.37887 -0.59423, 51.38018 -0.59206, 51.38109 -0.59086, 51.38306 -0.58805, 51.3844 -0.58548, 51.38549 -0.58273, 51.3879 -0.57429, 51.39021 -0.56749, 51.39183 -0.56344, 51.39364 -0.55938, 51.39781 -0.55101, 51.3987 -0.54861, 51.40083 -0.5416, 51.40187 -0.53944, 51.40233 -0.53786, 51.40221 -0.53679, 51.40197 -0.53619, 51.40156 -0.53571, 51.40091 -0.53546, 51.39954 -0.53593, 51.39874 -0.53593, 51.39483 -0.53373, 51.39255 -0.53166, 51.39073 -0.52946, 51.38941 -0.52744, 51.38612 -0.52151, 51.38435 -0.5183, 51.38173 -0.51445, 51.38053 -0.51309, 51.3791 -0.51178, 51.37656 -0.50984, 51.37211 -0.50772, 51.36923 -0.50599, 51.36738 -0.50448, 51.3657 -0.50273, 51.36104 -0.49779, 51.35756 -0.49448, 51.35308 -0.49025, 51.35079 -0.48773, 51.34962 -0.48671, 51.34841 -0.48595, 51.34731 -0.4855, 51.34621 -0.48524, 51.34347 -0.48524, 51.33955 -0.48504, 51.33643 -0.48421, 51.33345 -0.48275, 51.3326 -0.48214, 51.33031 -0.47973, 51.32904 -0.47789, 51.32809 -0.47627, 51.32686 -0.47351, 51.32576 -0.47025, 51.3253 -0.46794, 51.32478 -0.46416, 51.3246 -0.46203, 51.32419 -0.45855, 51.32363 -0.45568, 51.32189 -0.44907, 51.32012 -0.44432, 51.31799 -0.44002, 51.31476 -0.43285, 51.31141 -0.42433, 51.30819 -0.41523, 51.30656 -0.40764, 51.30599 -0.40284, 51.30596 -0.40107, 51.30618 -0.39735, 51.30672 -0.39385, 51.30805 -0.38844, 51.31035 -0.38077, 51.31106 -0.37774, 51.31221 -0.37184, 51.31268 -0.36825, 51.31309 -0.36135, 51.31342 -0.35522, 51.31388 -0.35235, 51.31495 -0.34771, 51.31538 -0.34592, 51.31579 -0.34315, 51.31591 -0.34011, 51.31584 -0.33885, 51.31525 -0.33478, 51.31431 -0.33159, 51.31325 -0.32916, 51.31139 -0.32613, 51.31016 -0.32482, 51.30751 -0.3231, 51.30535 -0.32177, 51.30293 -0.31986, 51.3009 -0.31783, 51.29883 -0.31529, 51.29745 -0.31319, 51.2963 -0.31104, 51.29482 -0.30718, 51.29404 -0.30411, 51.29363 -0.30174, 51.29295 -0.29387, 51.29221 -0.28796, 51.29157 -0.28449, 51.29051 -0.28037, 51.28878 -0.27562, 51.28658 -0.27121, 51.28423 -0.26751, 51.28255 -0.26529, 51.28081 -0.26334, 51.27846 -0.26136, 51.27549 -0.25953, 51.27328 -0.25752, 51.27205 -0.25605, 51.27061 -0.25378, 51.2676 -0.2475, 51.26259 -0.23699, 51.26043 -0.23171, 51.25895 -0.22669, 51.25802 -0.22171, 51.25763 -0.21622, 51.25767 -0.21098, 51.25803 -0.20457, 51.2589 -0.19782, 51.26034 -0.19159, 51.26217 -0.18624, 51.2633 -0.18369, 51.2648 -0.18087, 51.26605 -0.17803, 51.2669 -0.17554, 51.26772 -0.17221, 51.26832 -0.16892, 51.26872 -0.16537, 51.26884 -0.16242, 51.26878 -0.15998, 51.26851 -0.15774, 51.26813 -0.15591, 51.26703 -0.15235, 51.26596 -0.14801, 51.26533 -0.14369, 51.26509 -0.14025, 51.26504 -0.13716, 51.2649 -0.13356, 51.26499 -0.13076, 51.26479 -0.12965, 51.26384 -0.12792, 51.26278 -0.12626, 51.26227 -0.1258, 51.26159 -0.12549, 51.25924 -0.12558, 51.25727 -0.12505, 51.256 -0.12446, 51.25252 -0.12246, 51.24852 -0.11968, 51.24723 -0.11871, 51.24592 -0.11796, 51.24433 -0.11742, 51.24215 -0.11729, 51.23967 -0.11781, 51.23765 -0.11795, 51.23565 -0.11761, 51.23296 -0.11644, 51.23095 -0.11565, 51.22913 -0.11552, 51.22705 -0.11604, 51.2251 -0.11722, 51.2222 -0.11987, 51.21947 -0.12175, 51.21824 -0.12238, 51.21634 -0.12311, 51.21022 -0.12521, 51.2047 -0.12771, 51.20236 -0.12826, 51.19991 -0.12811, 51.1963 -0.12694, 51.1942 -0.12651, 51.19164 -0.12632, 51.18754 -0.12662, 51.17548 -0.12758, 51.16975 -0.12821, 51.16807 -0.12865, 51.16575 -0.12967, 51.16343 -0.13138, 51.16195 -0.13251, 51.16026 -0.13344, 51.15921 -0.13359, 51.15887 -0.13344, 51.15859 -0.13365, 51.15846 -0.13406, 51.15858 -0.13506, 51.15882 -0.13589, 51.15932 -0.13663, 51.15972 -0.1396, 51.15992 -0.14264, 51.15995 -0.14657, 51.15966 -0.15095, 51.15945 -0.15322, 51.15919 -0.15372, 51.15901 -0.15393, 51.15898 -0.15471, 51.15922 -0.15531, 51.15932 -0.15659, 51.15946 -0.16097, 51.16001 -0.1644, 51.16084 -0.16722, 51.16207 -0.17094, 51.16209 -0.17196, 51.16198 -0.17233, 51.16201 -0.17286, 51.16231 -0.17305, 51.16317 -0.17418, 51.16347 -0.17477, 51.16346 -0.17498, 51.16343 -0.17535, 51.16365 -0.1754, 51.16441 -0.17635, 51.16466 -0.17715, 51.1643 -0.18029, 51.16371 -0.18437, 51.16351 -0.18481, 51.16263 -0.18552, 51.16175 -0.18677, 51.16077 -0.18832, 51.16065 -0.18834, 51.16056 -0.18846, 51.15994 -0.18793, 51.15882 -0.18748, 51.15811 -0.18723, 51.15789 -0.18702, 51.15826 -0.18398)', 4326).MakeValid())>0
        

        你会看到'IDoNotWork'记录是真的不应该被选中的。

        非常感谢任何帮助。

        Diagram showing the two zones as rendered using Google Maps

        这是绘制为折线的完全相同的坐标。你可以看到它们不在区域附近。

        enter image description here

2 个答案:

答案 0 :(得分:10)

您的“IDoNotWork”地理位置实例存在环定向问题。具体而言,指定点的顺序(顺时针与逆时针)很重要。对于IDoNotWork实例,您定义了一个基本上是地球大小的区域(减去伦敦的一个小洞)。我是如何确定的?我选择了数据并查看了SQL Server Management Studio中的空间结果选项卡。对于此特定地理实例,边界框为(-90,90,-180,180)。每当我看到它时,对我来说这是一个很好的指示,多边形中的点的顺序与预期的相反。定义点有一个“右手”规则。也就是说,如果你驾驶汽车在你想要的地方开车时总是将多边形本身保持在汽车的右侧,那么你将按照正确的顺序遍历这些点。

我猜你正在使用SQL 2012,因为这在SQL 2008中会出错(你不可能有一个横跨半球的地理实例)。既然如此,你可以调用一个ReorientObject()方法,它会为你重新排序点。也许当你加载时你可以使用启发式(即“这个多边形的区域比它应该的大”),如果它失败,启发式调用ReorientObject就可以了。

TL; DR ::如果你颠倒你定义积分的顺序(见下文),你应该得到更多你正在寻找的东西。

INSERT INTO Polygons (ZoneName,Coordinates) VALUES ('IDoNotWork2',geography::STGeomFromText('POLYGON ((
    51.48822 -0.13046 
    , 51.50361 -0.14626
    , 51.52071 -0.15106
    , 51.52583 -0.1181
    , 51.52242 -0.09064
    , 51.51045 -0.07828
    , 51.49763 -0.09613
    , 51.48822 -0.13046)) '
, 4326))

答案 1 :(得分:0)

就我而言,我想根据我的表数据检查相交。我把它贴在这里给需要它的人

        DECLARE @geom geometry;
        SET @geom ='{geom}'; --replace your gemetry here
        SELECT A.RequestId ARedID, A.FarmerId,A.Status,A.WKT.STAsText() as WKT,A.WKT.STIntersection(@geom).STArea() as Int_AREA
        FROM tbl_RequestDetails A 
        where 
         and
        A.WKT.MakeValid().STIntersects(@geom) = 1 and 
        (A.WKT.MakeValid().STIntersection(@geom).STArea()/A.WKT.MakeValid().STArea()) > 0.3;