1

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

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

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

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

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

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

该表如下所示:

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

谢谢你的帮助!

4

2 回答 2

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 米。如果您不这样做,那么它将默认为您搜索的表格的坐标系单位。对于大地测量数据,这将始终是米。对于投影数据,它将是坐标系的单位 - 通常也是米,但并非总是如此。明确指定一个单位会消除所有歧义。

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

要对几何集合执行操作 - 即对于一组点,找到每个点的设定距离内的点,然后考虑使用 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;
于 2014-05-13T18:38:34.447 回答
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'
;

在这种情况下,距离采用由 a 的空间参考定义的线性单位。Oracle 将坐标视为笛卡尔坐标,因此您需要确保在使用此运算符之前拥有一个线性坐标系(与角度纬度/经度单位相反)。由于您使用的是北/东,我认为只要您要比较的点在同一个空间参考中,您就可以了。

这种方法使用内部循环来解决查询,如果您有很多要比较的点,那么效率不是很高。此外,Oracle Spatial 对 SDO 函数中的操作数顺序非常挑剔,因此您可能需要使用参数顺序来找到最佳位置。如果您的查询运行了很长时间,请尝试切换 sdo 运算符的第一个和第二个参数。您还可以使用/*+ ORDERED */后缀 after来处理 'from' 和 'inner join' 表的顺序SELECT

另一种方法是缓冲几何图形并与缓冲区进行比较。

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 的窗口位置(这是第二个参数)。这将确保您的空间索引被正确使用。

于 2012-08-14T12:37:30.167 回答