空间数据库之矢量数据上载方法

转载自:http://publishblog.blogchina.com/blog/tb.b?diaryID=5349656

摘  要:采用Oracle Spatial 存储、管理空间数据,易于解决数据共享、分布式处理、网络通信、开放式开发、并发控制、网络化集成、跨平台运行及数据安全恢复机制等方面的难题,因而成为了目前的一种应用趋势。而如何将现有GIS软件中产生的空间数据导入该数据库中成为该技术应用的首要关键环节。本文以此为出发点,在探讨了向Oracle Spatial 上载GIS的空间数据的基本原理的基础上,较全面地介绍了在Oracle Spatial中上载矢量数据与栅格数据的各种方法,重点介绍了使用 Microsoft的ADO接口、Oracle Spatial的Java API及OCCI接口等手工方式上载程序的实现过程。最后,给出了全文的结论及相关的建议。

1引言

空间数据是GIS的血液,对空间数据的管理的好坏将直接影响到GIS系统质量的高低。GIS空间数据的管理经过了纯文件方式管理图形数据与属性数据、图形数据文件方式管理与属性数据关系型数据库管理、空间数据与属性数据一体化的管理方式三个阶段。目前,大多数GIS 软件都逐渐倾向于采用第三种管理方式,也就是图形数据与属性数据都采用数据库管理的方式。例如,采用Oracle Spatial、DB2 Spatial Extender、Informix Spatial DataBlade(目前Informix已经被IBM收购)以及ArcSDE数据库引擎、MapGIS MapORA引擎等等。

Oracle Spatial提供了对象-关系模式和关系模式两种方式来存储空间数据。前者的特征是空间表中有一个类型为MDSYS.SDO_GEOMETRY的字段,后者也就是Spatial的早期版本空间数据暗盒(Spatial Cartridge),其特征是每一个空间几何图层对应四个表,分别为_SDOLAYER、_SDODIM、_SDOGEOM与_

SDOINDEX。这些表并不包括属性数据,属性数据需建立连接。目前许多GIS软件公司都提供了对Oracle Spatial的支持,比如Intergraph的GeoMedia 4.0、MapInfo的MapInfo 6.0、AutoDesk的MapGuide 6.0、ESRI的ArcSDE、ArcGIS以及国内中地公司的MapGIS 6.5等。

本文主要研究上载GIS的矢量数据和栅格数据到Oracle Spatial的原理与具体的各种实现方法,并在编程实践的基础上比较几种上载方法的优点与不足。

2 向Oracle Spatial上载GIS空间数据的原理

向Oracle Spatial上载GIS空间数据,其实质也就是把空间数据的图形数据(包括矢量数据与栅格数据)与相应的属性数据写入数据库的表格中。因此,在上载前必须清楚GIS空间数据的数据格式与Oracle Spatial中空间数据是如何存储的。

每个GIS软件拥有自己的内部数据格式和数据存储方式,大部分GIS软件并不向用户直接提供读写内部数据的函数。为了与其它软件进行数据转换,通常定义一种外部数据交换格式,如MapInfo的*.mif/*.mid、MapGIS的明码格式与ESRI的Shape格式(非ASCII码格式)等等。这些外部交换格式大部分为ASCII码文件,关于这些交换格式的数据结构的详细请参阅其公司发布的说明文档。

Oracle Spatial是一个对象-关系数据库,提供存储空间数据的类型是SDO_GEOMETRY。随着Oracle 10g的推出,又给Spatial扩充了拓扑数据模型、网络数据模型与栅格数据模型,每种数据模型都有其各自的数据类型,比如类型SDO_TOPOGEOMETRY用来存储拓扑数据等。在上载前一定要清楚这些数据类型的属性与方法,详细信息请参考文献1、2、3。

3 向Oracle Spatial上载GIS空间数据的方法

上载空间数据的方法,总的来说可以分为使用GIS软件公司提供的工具与手工的方式上载两种方法。本节主要介绍矢量数据与栅格数据的各种上载方法及其具体的实现过程。

3.1     矢量数据的上载方法

3.1.1    使用手工的方式实现上载

用户可以使用交互式的SQL语句上载GIS空间数据,使用这种方法也就是使用各种应用程序编程接口(如ADO、ODBC等等)来上载,用户可以以自己的应用需要为导向使用开发语言调用这些接口开发出各种各样的上载工具,即实现手工方式的加载。本小节介绍了重点介绍使用Microsoft的ADO接口以及Oracle Spatial的Java API和OCCI接口实现空间数据的上载的实现过程。

3.1.1.1   使用Java API上载

Oracle Spatial的Java API(Application Programing Interface)提供了3个类,即JGeometry、JGeometry.Point与DataException。JGeometry类对应于Oracle Spatial的对象类型MDSYS.SDO_GEOMETRY,JGeometry.Point类对应于对象类型MDSYS.SDO_POINT_TYPE, DataException类表示异常。下面的示例演示了如何使用Java API实现将GIS的空间数据写入Oracle Spatial中:

/// 从数据库中读取空间数据

ResultSet rs = statement.executeQuery("SELECT geoloc FROM countries where name='China'");

STRUCT st = (oracle.sql.STRUCT) rs.getObject(1);

//把结构体转换为geometry 对象

JGeometry j_geom = JGeometry.load(st);

// ... 在空间对象上执行空间操作或者创建新的空间对象 ...

/// 向数据库中存储空间对象

PreparedStatement ps = connection.prepareStatement("UPDATE countries set geometry=? where name=' China '");

//把JGeometry对象转换为数据库的结构体。

STRUCT obj = JGeometry.store(j_geom, connection);

ps.setObject(1, obj);

ps.execute();

3.1.1.2          OCCI上载示例

该上载示例是使用OCCI(Oracle C++ Call Interface)上载空间数据的完整示例程序。首先使用Oracle数据库数据类型翻译工具OTT(Oracle Type Translator)翻译类型MDSYS.SDO_POINT_TYPE与类型MDSYS.SDO_GEOMETRY,在命令行下输入,

ott attraccess=private code=cpp cppfile=spatial_classeso.cpp hfile=spatial_classesh.h intype=spatial_types.typ mapfile=spatial_classesm.cpp mapfunc=RegisterClasses userid=scott/tig

er@gis

命令成功执行以后,就会生成4个文件,分别为spatial_classesh.h、spatial_classeso.cpp、 spatial_classesm.h、与 spatial_classesm.cpp;

然后,在scott用户模式下创建空间表格(即存储空间数据的表格)spatial,实现的SQL语句如下:

CREATE TABLE spatial(geoloc MDSYS.SDO_GEOMETRY);

最后,利用VC++建立一个工程,把前面翻译的文件spatial_classesh.h、spatial_classeso.cpp、 spatial_classesm.h、与 spatial_classesm.cpp添加到工程中。主文件的内容为,

#include

#include

#include

#include

#include "spatial_classesh.h"

#include "spatial_classesm.h"

using namespace std;

using namespace oracle::occi;

const int SDO_GTYPE_2DPOINT = 2001;

const int SDO_GTYPE_2DPOLYGON = 2003;

const int SDO_ETYPE_POLYGON = 1003;

const int SDO_INTERPRETATION_RECTANGLE = 3;

void main()

{try

  {//以OBJECT模式初始化环境变量

    Environment *env = Environment::createEnvironment(Environment::OBJECT);

    RegisterClasses(env);//注册类型函数

    Connection *conn = env->createConnection("scott","tiger","gis");

   try

   { Statement *stmt = conn->createStatement("Insert Into spatial(geoloc) VALUES (:1)");

    //存储空间对象

    Number srid_null;

    SDOPointType *point_null = new SDOPointType();

    point_null->setNull();

    SDOGeometry *spatial_obj = new SDOGeometry();//建立对象

    spatial_obj->setSdo_gtype(SDO_GTYPE_2DPOLYGON);

    spatial_obj->setSdo_srid(srid_null);//不设置坐标系

    spatial_obj->setSdo_point(point_null);//设置点对象为null

    vector elem_info, ordinates;

    elem_info.clear();//清空elem_info

    ordinates.clear();//清空ordinates

    //存储elem_info对象

elem_info.push_back(1);elem_info.push_back(SDO_ETYPE_POLYGON);

    elem_info.push_back(SDO_INTERPRETATION_RECTANGLE);

    spatial_obj->setSdo_elem_info(elem_info);

//存储矩形,利用ordinates可以存储大于4000个字符的参数,ADO则小于4000

    ordinates.push_back(1);ordinates.push_back(1);// (1,1)

    ordinates.push_back(5);ordinates.push_back(7);// (5,7)

    spatial_obj->setSdo_ordinates(ordinates);

    stmt->setObject(1, spatial_obj);

    stmt->executeUpdate();

    delete spatial_obj;//释放对象

    conn->terminateStatement(stmt);}

   catch (SQLException &ex)

   {env->terminateConnection(conn);

    Environment::terminateEnvironment(env);

    throw; }

    env->terminateConnection(conn);

    Environment::terminateEnvironment(env); }

  catch (SQLException &ex)

  {cout << "Error running Demo : " << ex.getMessage() << endl; }}

编译成功之后,该工程就向Oracle Spatial的spatial表格中存储了一个矩形。用户可以扩展该工程,向数据库中存储以ASCII码表示的GIS软件的公开格式,比如MapInfo的*.mif/*.mid格式,MapGIS的点、线、区域、网络文件的明码数据等。

3.1.1.3          使用VB与ADO上载

各种应用程序接口也是有区别的,如果使用ADO的话,有可能会出现参数传递不能满足要求的情况,例如下面在VB6.0中使用ADO的语句,

Set adoCommand = Nothing

adoCommand.CommandType = adCmdText

adoCommand.CommandText = “Insert into SpatialTable_name(Spatial_column) values” & SpatialData

adoCommand.ActiveConnection = adoConnection

adoCommand.Execute

由于ADO Command对象的CommandText属性的长度如果超过4000个字符将不能进行值的传递。因此,对于较长的空间对象就需要被截断,所以,采用ADO接口进行上载不是最佳的选择。如果选择Oracle提供的应用程序编程接口(除了,前面提到的还可以使用OO4O、OCI等)就不会出现这种问题。因此建议采用Oracle提供的应用程序编程接口开发上载程序。

3.1.2              直接使用工具实现上载

目前许多GIS软件公司都提供了上载空间数据到Oracle Spatial中的工具,比如EasyLoader、ArcSDE、MapGIS等等。

3.1.2.1          EasyLoader

Easyloader是MapInfo公司提供的上载工具,不过该工具只支持上载MapInfo格式的*.tab数据。该工具提供了命令行上载与窗口上载两种方法。该工具在底层通过调用OCI(Oracle Call Interface)把数据写入数据库。使用EasyLoader上载空间数据到Oracle Spatial中,最大的优点就是上载的空间数据使用对象-关系模式存储的,可以完全利用Oracle Spatial的对象-关系模式的优点。在安装了MapInfo Professional以后,就默认安装了该工具,可以%MAPINFO%\Tools目录下找到该工具;此外,MapInfo的官方网站上也提供本免费工具的下载。

3.1.2.2          SQL*Loader与Shp2SDO

SQL*Loader根据从控制文件接受的指令读取ASCII码数据,并将数据放入Oracle数据库中。控制文件通知SQL*Loader数据应放在何处,并描述装入Oracle数据库中的各类数据。SQL*Loader还能过滤数据(即不装入那些不适合的数据),同时可以将数据装载进多个表,并在将数据放入Oracle表之前生成唯一关键字或操作数据。

Shp2SDO是Oracle公司提供的,用来把ESRI的*.shp文件转换为可以使用SQL*Loader的控制文件与数据文件的一个命令行工具。该工具不仅可以把*.shp转换为对象-关系的格式,也可以转换为关系格式。该工具可以从Oracle公司的网站上免费下载。

配合使用SQL*Loader与Shp2SDO就可以把ESRI的Shape文件上载到Oracle Spatial中。

3.1.2.3          ArcSDE与MapGIS提供的工具

如果购买了ESRI的ArcSDE,就可以使用ArcToolbox工具通过ArcSDE空间数据库引擎来上载ESRI格式的数据。与ArcMap或者ArcCatalog一样,ArcToolbox是ArcGIS家族的一个重要的成员,专门负责数据的导入导出工作。除了ESRI格式的数据以外(如ShapeFile、Covage文件),ArcToolbox还提供了E00、DWG等常用文件格式的数据转换工作。在进行数据转换的时候,用户可以根据实际的需要设置转换的参数,如空间数据表的字段名称,空间索引坐标的最值等。ArcToolbox给我们提供了良好的数据转换工具。同样,如果使用的MapGIS是6.5或者其更高版本的话,就可以使用MapGIS的属性库管理子系统、编辑子系统所提供的工具来上载MapGIS空间数据。虽然ArcSDE从逻辑上看是面向对象存储的,但是物理上使用的还是Oracle的纯关系表格。因此,这两个工具目前的版本只支持关系模式,也就是Spatial Cartridge的模式。

3.2     栅格数据的上载方法

从Oracle 10g开始,Oracle Spatial中增加了存储栅格数据的模块,同时还提供了上载栅格数据的Java API、PL/SQL API以及上载工具GeoRasterLoader。下面给出了使用GeoRasterLoader上载栅格数据的过程:

1)       CREATE TABLE jpegs (jpg MDSYS.SDO_GEORASTER);

2)       CALL sdo_geor_utl.createDMLtrigger(‘jpegs', 'jpg');

3)       CREATE TABLE rdt1 of MDSYS.SDO_RASTER (primary key (rasterId, pyramidLevel,bandBlockNumber, rowBlockNumber, columnBlockNumber));

4)       INSERT INTO jpegs VALUES(MDSYS.SDO_GEOR.init('rdt1'));

5)       SELECT jpg FROM jpegs;

返回值为SDO_GEORASTER(NULL, NULL, 'RDT1', 22, NULL)

6)       COMMIT;

7)       在操作系统的命令行工具使用下面的命令来上载栅格图像"C:\TEST.jpg",

java GeoRasterLoader gis01 gis 1521 scott tiger thin 32 T jpegs jpg "blocking=true,blocksize=(256,256,1)" "C:\TEST.jpg,22,rdt1";

8)       上载成功以后,还可以使用GeoRasterViewer来浏览栅格图像,在操作系统的命令行工具下输入下面的命令,

java GeoRasterLoader gis01 gis 1521 scott tiger thin 32 T;

在上载栅格数据的时候,由于目前的Oracle10.1.2版本所采用栅格数据模型不支持中文字符,所以用户在安装Oracle 10g的时候,必须选择使用英语,而不能默认使用中文。

4         结论

(1) 采用Oracle Spatial 存储、管理空间数据,易于解决数据共享、分布式处理、网络通信、开放式开发、并发控制、网络化集成、跨平台运行及数据安全恢复机制等方面的难题,因而成为了目前的一种应用趋势。而如何将现有GIS软件中产生的空间数据导入该数据库中成为该技术应用的首要关键环节。

(2) 向Oracle Spatial上载GIS空间数据,其实质也就是把空间数据的图形数据(包括矢量数据与栅格数据)与相应的属性数据写入数据库的表格中。而充分理解所导入的GIS数据的存储方式以及Oracle Spatial的数据类型及其对象的属性与方法是上载程序实现的工作基础。

(3) 在上载的实现方式上可以使用GIS件公司提供的工具或手工编写程序进行上载。在具体方式的选择上:如果GIS软件提供了相应的上载工具的话,建议采用这些工具上载,因为这样就可以利用相应的二次开发组件开发基于Oracle Spatial的应用程序(例如,使用Easyloader上载了*.tab文件后,就可以在MapInfo的MapX以及MapXtreme for Java中使用Oracle Spatial数据源);如果没有相应的上载工具,就用户可以通过ADO、OCI、OCCI、OO4O、Java API等接口自行开发上载工具。

(4) 在本文介绍的Java API、OCCI、ADO三种接口的实现过程中,由于ADO接口的 Command对象在CommandText属性的长度超过4000个字符的情况下不能进行值的传递,较长的空间对象会被截断。因此建议采用Oracle提供的Java API和OCCI接口来开发上载程序。

(5)Oracle10g 的Oracle Spatial选件中增加了存储栅格数据的模块,同时还提供了上载栅格数据的Java API、PL/SQL API以及上载工具GeoRasterLoader。使用GeoRasterLoader可以实现栅格数据的上载,但是由于目前的Oracle10.1.2版本所采用栅格数据模型不支持中文字符,所以建议在安装时的语言的选项上不采用默认的中文而选择使用英语。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值