您的位置:首页 > 数据库 > Oracle

Oracle Spatial研究

2012-09-21 08:27 127 查看
Oracle Spatial是Oracle公司推出的空间数据库组件,通过Oracle数据库系统存储和管理空间数据。 Oracle从9i开始对空间数据提供了较为完备的支持。

由于Oracle Spatial本身是ORACLE数据库的一个特殊的部分,因此可以用ORACLE提供的程序接口来对Oracle Spatial管理的空间数据进行操作。目前,ORACLE数据库主要提供两种接口方式对其数据进行存取:


ORACLE提供的面向C语言程序员的编程接口OCI(Oracle Call Interface,简称OCI);

• 用ORACLE本身所提供的OLE对象(Oracle Objects for OLE,以下简称OO4O)来快速访问有关数据库。


ORACLE对OCI接口进行了封装,提供了C++语言的接口OCCI(Oracle C++ Call Interface),采用面向对象的方式封装,面向C++程序员。

Oracle Spatial主要通过元数据表、空间数据字段(即SDO_GEOMETRY字段)和空间索引来管理空间数据,并在此基础上提供一系列空间查询和空间分析的函数,让用户进行更深层次的GIS应用开发。Oracle
Spatial使用空间字段SDO_GEOMETRY存储空间数据,用元数据表来管理具有SDO_GEOMETRY字段的空间数据表,并采用R树索引和四叉树索引技术来提高空间查询和空间分析的速度。

1、元数据表说明

Oracle Spatial的元数据表存储了有空间数据的数据表名称、空间字段名称、空间数据的坐标范围、坐标参考信息以及坐标维数说明等信息。用户必须通过元数据表才能知道ORACLE数据库中是否有Oracle Spatial的空间数据信息。一般可以通过元数据视图(USER_SDO_GEOM_METADATA)访问元数据表。元数据视图的基本定义为:

SQL> desc USER_SDO_GEOM_METADATA

名称 是否为空?类型

----------------------------------------- -------- -------------------



TABLE_NAME NOT NULL VARCHAR2(32)

COLUMN_NAME NOT NULL VARCHAR2(1024)

DIMINFO MDSYS.SDO_DIM_ARRAY

SRID NUMBER



其中,TABLE_NAME为含有空间数据字段的表名,COLUMN_NAME为空间数据表中的空间字段名称,DIMINFO是一个按照空间维顺序排列的SDO_DIM_ELEMENT对象的可变长度数组,SRID则用于标识与几何对象相关的空间坐标参考系。SDO_DIM_ELEMENT对象的定义如下所示:

Create Type SDO_DIM_ELEMENT as OBJECT (

SDO_DIMNAME VARCHAR2(64),

SDO_LB NUMBER,

SDO_UB NUMBER,

SDO_TOLERANCE NUMBER);

其中,SDO_DIMNAME是空间维名称,SDO_LB为该空间维的左下角坐标,SDO_UB为该空间维的右上角坐标,SDO_TOLERANCE为几何对象的容差。

元数据插入例子:

INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID)

VALUES ('BOUNT_POLY', 'GEOM',

MDSYS.SDO_DIM_ARRAY

(MDSYS.SDO_DIM_ELEMENT('X', 73.446960000, 135.085830000, 0.000000050),

MDSYS.SDO_DIM_ELEMENT('Y', 6.318641200, 53.557926000, 0.000000050)

),

NULL);



2、空间字段解析(SDO_GEOMETRY数据类型)

Oracle存储空间数据是通过SDO_GEOMETRY数据类型存储的,在这种机制下,Oracle能实现空间数据和属性数据一体化存储。理解SDO_GEOMETRY是编写Oracle
Spatial接口程序的关键。SDO_GEOMETRY是基本按照OpenGIS规范定义的一个对象,其原始的创建方式如下所示。

CREATE TYPE sdo_geometry AS OBJECT (

SDO_GTYPE NUMBER,

SDO_SRID NUMBER,

SDO_POINT SDO_POINT_TYPE,

SDO_ELEM_INFO MDSYS.SDO_ELEM_INFO_ARRAY,

SDO_ORDINATES MDSYS.SDO_ORDINATE_ARRAY);



该对象由五个部分组成,解释如下:

(1)SDO_GTYPE

SDO_GTYPE是一个NUMBER型的数值,用来定义存储对象的类型。SDO_GTYPE是一个4个数字的整数,其格式为dltt,其中d表示几何对象的维数;l表示三维线性参考系统中的线性参考值,当d为3维或者4维时需要设置该值,当d为2的情况下为空;tt为几何对象的类型,Oracle
Spatial定义了7种类型的几何类型,目前,tt使用了00到07(包括一种用户自定义类型),另外,08到99是Oracle
Spatial保留的数字,以备将来几何对象扩展所用。



(2)SDO_SRID

SDO_SRID也是一个NUMBER型的数值,它用于标识与几何对象相关的空间坐标参考系。如果SDO_SRID为空(null),则表示没有坐标系与该几何对象相关;如果该值不为空,则该值必须为MDSYS.CS_SRS表中SRID字段的一个值,在创建含有几何对象的表时,这个值必须加入到描述空间数据表元数据的USER_SDO_GEOM_METADATA视图的SRID字段中。Oracle
Spatial规定,一个几何字段中的所有几何对象都必须为相同的SDO_SRID值。



(3)SDO_POINT

SDO_POINT是一个包含X,Y,Z数值信息的对象,用于表示几何类型为点的几何对象。如果SDO_ELEM_INFO和SDO_ORDINATES数组都为空,则SDO_POINT中的X,Y,Z为点对象的坐标值,否则,SDO_POINT的值可以忽略(用NULL表示)。Oracle
Spatial强烈建议用SDO_POINT存储空间实体为点类型空间数据,这样可以极大的优化Oracle Spatial的存储性能,提高查询效率。



(4)SDO_ELEM_INFO

SDO_ELEM_INFO是一个可变长度的数组,每3个数作为一个元素单位,用于解释坐标是如何存储在SDO_ORDINATES数组中的。通常把组成一个元素的3个数称为3元组。一个3元组包含以下3部分的内容:

l
Offset

Offset表明每个几何元素的第一个坐标在SDO_ORDINATES数组中的存储位置。它的值从1开始,逐渐增加。

l
ETYPE

ETYPE 用于表示几何对象中每个组成元素的几何类型。与SDO_GTYPE类型中的T值相对应。

l
INTERPRETATION

INTERPRETATION说明了几何体所包含的更细微的信息。对于一个点来说,INTERPRETATION是1;对于线串和多边形来说,如果是通过直线连接的,则INTERPRETATION是1;如果是通过弧连接的,则INTERPRETATION是2。对于多边形,可以把INTERPRETATION设为3,表示多边形是一个矩形。例如,如果线串通过直线连接,那么SDO_ELEM_INFO为(1,2,1)。



(5)SDO_ORDINATES

SDO_ORDINATES是一个可变长度的数组,用于存储几何对象的真实坐标,该数组的类型为NUMBER型,它的最大长度为1048576。SDO_ORDINATES必须与SDO_ELEM_INFO数组配合使用,才具有实际意义。SDO_ORDINATES的坐标存储方式由几何对象的维数决定,如果几何对象为三维,则SDO_ORDINATES的坐标以{X1,Y1,Z1,X2,Y2,Z2,…..}的顺序排列,如果几何对象为二维,则SDO_ORDINATES的坐标以{X1,Y1,X2,Y2,…..}顺序排列。



3、基于OCCI的Oracle Spatial接口程序实现

要对Oracle Spatial进行操作,首先需要建立与Oracle数据库的连接,可以用以下语句完成对数据库的连接工作。

env =
Environment::createEnvironment(Environment::OBJECT);
mappings(env); //映射函数
try
{
assert(env !=NULL);
conn =
NULL;
conn =
env->createConnection(username,password,connString);
}
catch (SQLException*e)
{
int
errNum = e->getErrorCode();
string
errMsg = e->getMessage();
}

当把数据读入结果集中后,才可以解析空间数据,下面的代码是对SDO_GEOMETRY字段的解析(以点对象为例):

OGRGeometry *COracleDBOperation::CreateFromGeom(SDO_GEOMETRY*geometry)
{
vector<Number>vec =geometry->getsdo_ordinates(); //坐标数组
int
gtype = int(geometry->getsdo_gtype()); //获取几何体类型
if (2001 ==
gtype || 1 == gtype)
//点类型
{
OGRPoint*
poPoint = new
OGRPoint();
if (geometry->getsdo_point())
{
double
x = double(geometry->getsdo_point()->getx());
double
y = double(geometry->getsdo_point()->gety());
poPoint->setX(x);
poPoint->setY(y);
}
else
{
poPoint->setX(double(vec[0]));
poPoint->setY(double(vec[1]));
}
return
poPoint;
}
}
注意:当同样空间数据存入数据库中后读写的数据没有文件存储方式快。

因为数据库读写需要连接数据库,还要进行SQL语句的解析,经过测试,直接读取文件会快一点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: