Oracle Spatial研究

长平狐 发布于 2013/12/25 17:25
阅读 289
收藏 0

Oracle SpatialOracle公司推出的空间数据库组件,通过Oracle数据库系统存储和管理空间数据。 Oracle9i开始对空间数据提供了较为完备的支持。

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

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

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

    ORACLEOCI接口进行了封装,提供了C++语言的接口OCCIOracle 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);

 

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

1SDO_GTYPE

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

 

2SDO_SRID

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

 

3SDO_POINT

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

 

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

 

5SDO_ORDINATES

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

 

3、基于OCCIOracle 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语句的解析,经过测试,直接读取文件会快一点。


原文链接:http://blog.csdn.net/zhouxuguang236/article/details/8002574
加载中
返回顶部
顶部