Oracle Spatial - 选择落在区域内的对象

时间:2012-08-14 11:00:43

标签: oracle oracle10g geospatial oracle-spatial

这对于那些知道的人来说可能很简单(我希望!)

我有一个Oracle空间数据库,其中包含一个包含节点点列表的几何列,采用北/东格式(如果它是相关的!)

我需要选择落在给定点的给定半径范围内的那些对象。

Northings和Eastings相距1米,这使它更容易。

理想情况下,这应该包括跨越该区域的对象,即使它们的节点落在它之外。

这是一个简单的查询吗?也许使用SDO_WITHIN_DISTANCE?

表格如下:

MyTable
ID NUMBER
NAME VARCHAR2(20)
DESC VARCHAR2(50)
GEOM SDO_GEOMETRY

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您可以通过以下两种方式之一完成此操作。首先,正如您所提到的,SDO_WITHIN_DISTANCE是一种有效的方法。

select 
    *
from center_point a
inner join target_points b
    on a.id = 1
    and sdo_within_distance( b.shape, a.shape, 'distance = 10' ) = 'TRUE'
;

在这种情况下,距离是由空间参考定义的线性单位。 Oracle将坐标视为笛卡尔坐标,因此在使用此运算符之前需要确保您具有线性坐标系(而不是角度lat / lon单位)。既然你正在北方/东方工作,我认为只要你所比较的点在相同的空间参考中你就会没事。

如果你有很多要比较的点,这种方法使用内循环来解决查询,因此效率不高。此外,Oracle Spatial对SDO函数中操作数的顺序非常挑剔,因此您可能需要使用参数顺序来查找甜点。如果查询运行很长时间,请尝试切换sdo运算符的第一个和第二个参数。您还可以使用/*+ ORDERED */之后的SELECT后跟来播放“来自”和“内部联接”表格的顺序。

另一种方法是buffer the geometry并与缓冲区进行比较。

select 
    *
from center_point a
inner join target_points b
    on a.id = 1
    and sdo_relate( b.shape, sdo_buffer(a.shape, 0.05 ), 'mask=anyinteract' ) = 'TRUE'
;

请记住,SDO_RELATE的第二个参数(称为窗口)中的任何内容都不会有空间索引,如果你像我们在这里使用缓冲区那样进行变换。

如果您计划使用多个点进行此操作,建议构建一个表,其中缓冲所有源点。然后针对缓冲区域创建空间索引,并将其与目标点进行比较。

例如:

create table point_bufs unrecoverable as
select sdo_buffer (a.shape, b.diminfo, 1.35)
from centerpoint a, user_sdo_geom_metadata b
where table_name='CENTERPOINT'
  and column_name='SHAPE';

select
    a.gif,
    b.gid 
from target_points a, 
     point_bufs b
where sdo_relate(a.shape, b.shape, 'mask=anyinteract querytype=join') = 'TRUE'
;

注意:当与多边形相交的点时,您总是希望多边形位于sdo_relate的窗口位置(这是第二个参数)。这将确保正确使用您的空间索引。

答案 1 :(得分:1)

使用SDO_WITHIN_DISTANCE的正确方法,无论使用何种坐标系,无论是投影还是大地测量,都是如此:

select b.*
from my_table a, my_table b
where a.id = 1
and sdo_within_distance( b.shape, a.shape, 'distance=10 unit=meter' ) = 'TRUE';

空间谓词的参数顺序很重要:第一个是您要搜索的点,第二个是"查询窗口",即您要搜索的点。请注意,您应始终指定距离的单位 - 此处为10米。如果你没有,那么它将默认为你搜索的表的坐标系的单位。对于大地测量数据,它总是米。对于投影数据,它将是您坐标系的单位 - 通常也是米,但并非总是如此。明确指定一个单元可以解除所有歧义。

您也可以使用缓冲区方法,但这没有区别,实际上速度较慢。空间谓词的第二个参数是否被索引并不重要:不使用该索引。只需要使用 first 参数的索引。

要对几何集合执行操作 - 即对于一组点,找到每个点的设定距离内的点,然后考虑使用SDO_JOIN()函数,像这样找到所有几个点距离彼此不到10米:

SELECT a.id, b.id
  FROM my_table a,
       my_table b,
       TABLE(SDO_JOIN(
             'MY_TABLE', 'SHAPE',
             'MY_TABLE', 'SHAPE',
             'DISTANCE=10 UNIT=METER')
       ) j
WHERE j.rowid1 = a.rowid
  AND j.rowid2 = a.rowid
  AND a.rowid < a.rowid;