gis
gis
管理员
管理员
  • 注册日期2003-07-16
  • 发帖数15899
  • QQ491474196
  • 铜币10742枚
  • 威望809点
  • 贡献值0点
  • 银元0个
  • GIS帝国居民
  • 帝国沙发管家
  • GIS帝国铁杆
阅读:1775回复:0

Oracle Spatial研究

楼主#
更多 发布于:2015-05-17 12:11

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语句的解析,经过测试,直接读取文件会快一点。
喜欢0 评分0
游客

返回顶部