直接在多边形前面使用Oracle Spatial查找点

时间:2014-11-19 15:39:01

标签: database spatial spatial-query oracle-spatial

我有很多多边形和许多点,并希望找到这样的点,当在该点和多边形之间绘制一条线时,它不与任何其他多边形相交。所以基本上我需要一个非常靠近多边形的点,它们之间没有其他多边形。

我尝试了以下查询,它给出了所有点,无论它们是否与多边形相交。

SELECT P.POINTLOC from pointTable P WHERE NOT MDSYS.SDO_OVERLAPBDYINTERSECT(P.POINTLOC," +
            "MDSYS.SDO_GEOMETRY(2003,null,null,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1)," +
"MDSYS.SDO_ORDINATE_ARRAY(4, 226, 150, 254, 164, 240, 191, 212, 176,4,226)))    = 'TRUE'";

Then I tried this query and it gives some correct points but miss a few correct points:

SELECT P.POINTLOC from pointTable P WHERE MDSYS.SDO_WITHIN_DISTANCE(P.POINTLOC," +
            "MDSYS.SDO_GEOMETRY(2003,null,null,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1)," +
"MDSYS.SDO_ORDINATE_ARRAY(4, 226, 150, 254, 164, 240, 191, 212, 176,4,226)),'distance = 40')    = 'TRUE'";

有人可以指出哪种Oracle空间运算符最适合这种情况吗?

1 个答案:

答案 0 :(得分:0)

听起来您正在寻找最近邻实现 - Oracle提供了Spatial运算符SDO_NN

您可以在此处找到更多详细信息: http://docs.oracle.com/database/121/SPATL/sdo_operat.htm#SPATL1032

这只会让你到目前为止,因为它会找到最接近多边形的点,但不能保证你的点和目标多边形之间没有多边形。我怀疑如果你想确保这一点,你必须要有创意。

我的方法是:

  1. 使用SDO_NN获取最近的一个或多个点
  2. 使用SDO_GEOM.SDO_CENTROID查找多边形重心
  3. 创建一个加入两点的查询/内存中SDO_GEOMETRY
  4. 使用此作为NOT EXISTS子句的基础,以排除多边形与该行相交的点
  5. 可能是以下未经测试/未完成的示例:

    SELECT *
    FROM points pnt
    WHERE sdo_nn(pnt.point, sdo_geometry(your polygon here)) = 'TRUE' -- fill this with your polygon
    AND NOT EXISTS (
      SELECT 1
      FROM polygons plg
      WHERE sdo_geom.sdo_intersection(
        plg.polygon
      , sdo_geometry(
          2002
        , NULL -- oracle srid
        , NULL -- point
        , sdo_elem_info_array(1, 2, 1) -- line
        , sdo_ordinate_array(
          , sdo_geom.sdo_centroid(
              sdo_geometry(your polygon here) -- fill this with your polygon
            , 0.05
            ).x
          , sdo_geom.sdo_centroid(
              sdo_geometry(your polygon here) -- fill this with your polygon
            , 0.05 -- tolerance
            ).t
          , pnt.point.sdo_point.x
          , pnt.point.sdo_point.y
          ) -- line between point and polygon centroid
        )
      , 0.05 -- tolerance
      ) = 'TRUE'
    ) 
    

    根据您的数据集/性能,您可能希望使用集合或循环在PL / SQL中执行此操作。

    上面的例子有点粗糙,准备好了,但我希望你能得到主旨。